Werkzeug: リローダーから呼び出されたWindowsコンソールスクリプト

作成日 2017年06月13日  ·  14コメント  ·  ソース: pallets/werkzeug

Python 3でapistarを実行していますが、werkzeugリローダーにつながる問題が発生しています。

(fresh) C:\Users\uskaxb07\PycharmProjects\testapi>apistar run
Starting up...
 * Restarting with stat
  File "C:\Users\uskaxb07\env\fresh\Scripts\apistar.exe", line 1
SyntaxError: Non-UTF-8 code starting with '\x90' in file C:\Users\uskaxb07\env\fresh\Scripts\apistar.exe on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

run_simple()の呼び出しからuse_reloaderを削除すると機能します。 いくつかのコメントを掘り下げた後、 https://github.com/pallets/werkzeug/blob/master/werkzeug/_reloader.py#L118がlatin1にエンコードを行っていることがわかりましたが、OSがWindowsでPythonバージョンの場合のみです。は2です。これにより、python3で受信しているUTF-8以外の構文エラーが発生している可能性がありますか?

全てのコメント14件

これを再現するために使用できる小さな例はありますか? 私はapistarの使用に慣れておらず、Windowsを定期的に使用していません。

もう少し掘り下げました。 問題は実際には_get_args_for_reloading()にあります。 このメソッドは['python.exe', 'apistar.exe', 'run']引数を返し、 subprocess.call()に渡されるとそのエラーが生成されます。 コマンドラインからpython.exe apistar.exe runを呼び出すのと同じです。

したがって、問題は私が当初考えていたような環境エンコーディングではありません。 他のwerkzuegベースのフレームワークで非常に一般的に発生することを考えると、console_scriptで生成された.exeを介して呼び出すことができるという事実を考慮してこのメ​​ソッドを変更すると、すべてのWindowsユーザーにメリットがあると思います。

これを考慮して、問題のタイトルを変更しています。

このメソッドがウィンドウのチェック内でrvのsys.executable要素を破棄した場合、リロードは成功します。

def _get_args_for_reloading():
    """Returns the executable. This contains a workaround for windows
    if the executable is incorrectly reported to not have the .exe
    extension which can cause bugs on reloading.
    """
    rv = [sys.executable]
    py_script = sys.argv[0]
    if os.name == 'nt' and not os.path.exists(py_script) and \
       os.path.exists(py_script + '.exe'):
        py_script += '.exe'
        rv.pop()
    rv.append(py_script)
    rv.extend(sys.argv[1:])
    return rv

提出したい場合は、PRを確認させていただきます。

私は絶対にやりたいのですが、私はこれのテストを書くことに少し立ち往生しています。 これがunittest.mockライブラリで機能し、sys.executableとos.nameにパッチを適用していることだけがわかりますが、27でも自動テストをサポートする必要があるため、これはプロジェクトでは機能しないと思います。 何かアドバイス?

また、ここで使用される分岐戦略は何ですか? 問題のプルリクエストは、現在のメンテナンスブランチに反しますか?

0.12メンテナンスから分岐できます。 最初にパッチがどのように見えるかを見てから、テストを理解しましょう。

プルリクエストを送信しました。 私が行った変更とは関係のない理由で、TravisCIが失敗しているようです。 これは私の最初のプルリクエストなので、ここからどこに行けばいいのかわかりません。

これは、setuptoolsがexeランチャーをインストールしている場合に発生します。 最新のpipを介してインストールすると、Pythonが直接実行できるzip内のexeにランチャースクリプトをバンドルする新しい種類のexeランチャー( distlibから)がインストールされます( runpy docs )。

これは、これが修正されるべきではないという意味ではありませんが、これを再現できない場合に備えて知っておくと役に立ちます。 たとえば、Flaskを開発モード( pip install -e )でインストールした場合でも発生します。

@androiddrew @davidismこのPRの更新はありますか?

@segevfiner最近のコメントにもう少し詳細を追加できますか? Flaskではなくsetuptoolsで根本原因を修正する必要があることを示唆していますか?

@ewpete根本的な原因は、setuptoolsで生成されたランチャーを使用する場合、
sys.argv [0]は、Pythonスクリプトであるため、Pythonスクリプトとして実行できません。
ランチャーexe。 実際のスクリプトは、exeのように-"-script"で名前が付けられます。
追加され、exeがロードされて実行されます。

exeを直接実行できることに注意してください(Pythonスクリプトも同様です)
setuptoolsがユニスで生成するものであると私が信じているシバンで)。 しかし
Windows上のプレーンなPythonスクリプトに対してそうすることは信頼できません(
pylauncherはインストールされていません)、任意のPythonで起動するため
レジストリ内の.pyファイルに関連付けられていますが、異なる場合があります
現在使用しているPythonよりも。 そしてもちろん、同じことが当てはまります
呼び出される可能性のあるランダムなPythonスクリプト。
実行可能。

代わりに、pipは(distlibを介して)新しい種類のexeランチャーをインストールします。
生成されたランチャースクリプトは、zip内の最後に追加されます
実行可能。 これは、__ main__。pyスクリプト(A
zipapp)であり、Pythonに直接渡して実行することができます。

setuptoolsでこれを修正することは、類似/同じ種類のbofを生成することを意味します
setuptoolsのランチャー。 そしてhttp://xkcd.com/1172/の精神で、これは
setuptoolsランチャーを期待して試行するコードを壊す可能性があります
「* -script.py」ファイルを使用して問題を回避します。 確認しなかった
これについてすでに問題/広報があるかどうか。

Werkzeugがそうするように、ここに小さな回避策があるのはおそらく問題ありません。
リローダーは、setuptoolsの現在のスタイルが存在する場合でも機能します
ランチャー。 しかし、それは本当にプロジェクトのメンテナ次第です。

בתאריך28בנוב'201720:46、 "ewpete" [email protected] כתב:

@androiddrew https://github.com/androiddrew @davidism
https://github.com/davidismこのPRの更新はありますか?

@segevfinerhttps ://github.com/segevfinerもう少し追加できますか
最近のコメントの詳細は? あなたは私たちがすべきだと提案していますか
おそらくFlaskではなくsetuptoolsで根本的な原因を修正しますか?


あなたが言及されたので、あなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/pallets/werkzeug/issues/1136#issuecomment-347623921
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/AXlg_8OSR3NdbPJzM87dyKPUAA9NpXJ6ks5s7FT7gaJpZM4N5Fcb
.the

@ewpeteこれは私の最初のPRでした。 私はテストを書き、開発ガイドに従い、PRを配置するために最善を尽くしました。 これを行う方法についてはあまり方向性がありませんでしたが、PRコメントから提案された変更を加えました。 完成したと思いましたが、プロジェクトチームの期待に応えたかどうかは聞かれませんでした。 それ以来それを見ていません、そして私は人々がそれで何をしたいのか分かりません。

複数のプロジェクトにまたがる時間は非常に限られています。 心配しないでください、これを忘れていません。

@davidism応答するだけでなく、これらのプロジェクトを存続させるための良い仕事をしてくれてありがとう!

これはまだマージされていませんが、一時的な修正の1つとして、 _get_args_for_reloading()関数を使用する前にどこかにモンキーパッチを適用することが考えられます。 Flaskスクリプトの場合、これをmanage.pyファイルの先頭のどこかに追加すると次のようになります。

import werkzeug._reloader
import os, sys

def _get_args_for_reloading():
    rv = [sys.executable]
    py_script = sys.argv[0]
    if os.name == 'nt' and not os.path.exists(py_script) and \
       os.path.exists(py_script + '.exe'):
        py_script += '.exe'
    if os.path.splitext(rv[0])[1] == '.exe' and os.path.splitext(py_script)[1] == '.exe':
        rv.pop()
    rv.append(py_script)
    rv.extend(sys.argv[1:])
    return rv
werkzeug._reloader._get_args_for_reloading = _get_args_for_reloading
このページは役に立ちましたか?
0 / 5 - 0 評価