2

私はpy2exeでコンパイルされたpythonプログラムを1台のサーバーマシンから多数のクライアントマシンで実行しています(すべてのマシンのネットワークドライブにマップされています.W :など)。

Windows XP 以降のマシンでは、これまでのところ、Python が W:\python23.dll を拾うという問題はありませんでした (はい、私は W98 との互換性のために Python 2.3.5 を使用しています)。次に、W:\zlib.pyd を使用して、os などのすべての .pyc ファイルを含む W:\library.zip を解凍します。これらはインポートされ、プログラムは問題なく実行されます。

この問題は、一部の Windows 98 SE マシンで発生しています (注: 一部の Windows 98 SE マシン、その他は明らかな問題なく動作するようです)。何が起こるかというと、プログラムは W: から実行され、W:\python23.dll が見つかったと思います (Python の ImportErrors が発生しているため、Python の import ステートメントを実行できる必要があります)。いくつかのことが機能しません:

1) W:\library.zip に .pyc ファイルの唯一のコピーが含まれている場合、 ZipImportError: can't decompress data; zlib not available(W:\zlib.pyd が利用可能であり、同じネットワーク上の XP 以降のマシンで正常に動作することを考えるとナンセンスです)。

2) .pyc ファイルが py2exe によって python exe 内に実際にバンドルされている場合、または .exe と同じディレクトリに置かれている場合、または PYTHONPATH 変数の一部として設定される名前付きサブディレクトリに置かれている場合 (例: W:\pylib) )、取得しますImportError: no module named os(os は、sys などの前にインポートされた最初のモジュールです)。

考えてみると、osがインポートされる前にsys.pathを検索できなかったのでしょうか?これらのインポートの順序を変更してみますが、私の疑問はまだ残っています:なぜこれは散発的な問題で、一部のネットワークでは機能し、他のネットワークでは機能しないのですか? また、実行する実行可能ファイル内にバンドルされているファイルを Python に強制的に検索させるにはどうすればよいでしょうか。私は稼働中の Windows 98 SE マシンにすぐにアクセスできますが、稼働していないマシン (私の顧客) には、毎朝店が開く前にしかアクセスできません。

前もって感謝します!


編集:さて、大きな一歩前進。PY2EXE_VERBOSE でデバッグした後、特定の W98SE マシンで発生する問題は、インポートを探すときに正しいパス構文を使用していないことです。まず、PYTHONPATH 環境変数を読み取っていないようです (PY2EXE_VERBOSE のように、私が認識していない py2exe 固有のものがある可能性があります)。

第 2 に、あきらめる前に 1 か所だけを検索します (ファイルが EXE 内にバンドルされている場合は、そこを検索します。そうでない場合は、library.zip を検索します)。

EDIT 2 : 実際、thisによると、Python インタープリターの sys.path と Py2exe 実行可能ファイルの sys.path には違いがあります。具体的には、sys.path contains only a single entry: the full pathname of the shared code archive.何とか。フォールバックはありませんか?現在の作業ディレクトリでさえありませんか?PATH に追加してみW:\ますが、py2exe はシステム ライブラリを検索するための標準に準拠していないため、機能しません。

さて、興味深い点です。atexit、os などをロードしようとするパスは次のとおりです。

W:\\library.zip\<module>.<ext>

library.zip の後の 1 つのスラッシュですが、ドライブ文字の後の 2 つのスラッシュに注意してください (これが意図されていて動作する場合は、誰かが私を修正してください)。これが文字列リテラルの場合、スラッシュが二重にされていないため、(無効な) エスケープ シーケンスとして読み取られ、生の文字が出力されます (W:\library.zipos.pyd, W:\library.zipos.dll, ...スラッシュの代わりに表示されます)。文字列リテラルでない場合、二重スラッシュは自動的にノルムパス化されない可能性があり (そうあるべきです)、二重スラッシュはモジュール ローダーを混乱させます。私が言ったように、set PYTHONPATH=W:\\library.zip\\その変数を無視するという理由だけではできません。

プログラムの開始時に sys.path.append を使用する価値があるかもしれませんが、特に古い OS の 1 つの構成で問題が発生するため、ハードコーディング モジュール パスは絶対的な最後の手段です。

何か案は?私は 1 つを持っていsys.pathますos。もう 1 つは、追加os.getenv('PATH')するかos.getenv('PYTHONPATH')、sys.path に追加することです... 再び、osモジュールが必要です。モジュールも初期化に失敗するsiteため、.pth ファイルを使用できません。

また、最近、プログラムの開始時に次のコードを試しました。

for pth in sys.path:
    fErr.write(pth)
    fErr.write(' to ')
    pth.replace('\\\\','\\') # Fix Windows 98 pathing issues
    fErr.write(pth)
    fErr.write('\n')

しかし、それは linecache.pyc やその他のものをロードすることはできません。見た目からは実際にこれらのコマンドを実行することはできません。sys.path を動的に変更するために linecache を必要としない組み込み機能を使用する方法はありますか? それとも、正しい sys.path をハードコーディングする必要がありますか?

4

1 に答える 1

2

これは直接的な答えではありませんが、おそらくいくつかの助けになります。-vPythonのオプションに精通していますか。入力python -hして詳細を確認してください。py2exe で実行されPYTHONVERBOSEスクリプトの環境変数に相当するものは であることに注意してください。基本的にandのように 1 または 2 の値を取ることができるようですが、PYTHONVERBOSEの動作とは少し異なります。PY2EXE_VERBOSE-v-vv

sys.path のアイデアについても注意してください。sys既にインポートしているかどうかは、インポートできるかどうかに影響しませんos。つまりsys.path、sys モジュールをインポートしたかどうかに関係なく、そこにあるインタープリターの内部機能を反映しているという意味で、Python パス ( で表示) は常に使用可能です。

他の多くのモジュールと同様に、sysが組み込まれているため、アプリがほぼ完全に機能しなくなった場合でも、常にインポートできるはずです。sys.builtin_module_namesそれが役立つ場合は、Python のバージョンでそれらが何であるかを確認するために使用できる場合があります。インタープリターが実行されている場合、その情報がすべて利用可能になるため、以下は、取得したものを確認するために作成できる最小の便利なプログラムである可能性があります。

import sys
print sys.builtin_module_names

また、.pyc ファイルを .exe 内にバンドルするなど、手の込んだことはお勧めしません。Win98 のサポートに行き詰まるのを防ぐために、あなたはすでに十分な努力をしてきました。もし私があなたなら、仕事を終わらせてより興味深い分野に進むことができる最も単純な方法を選びます。Python を普通にインストールしてソースから実行できるのであれば、ぜひ検討してみてください。:)

darvids0n によるコメントごとに PY2EXE_VERBOSE 情報へのリンクを含めるように編集。

于 2010-01-05T23:42:50.820 に答える