PyInstaller 2.0 バンドルファイルを --onefile として質問する

PyInstaller 2.0 バンドルファイルを --onefile として質問する

PyInstaller 2.0 を使用して、py スクリプトを .exe としてバンドルしようとしています。スクリプトをバンドルすることはできますが、スクリプト内で、exe にバンドルする必要があるファイル (移植可能) を開く必要があります。これを実行するのに問題があります。

私の.pyでは、

filename = 'C:\path\to\my\file\doc.docx'
data = open(filename,'rb')

私は PyInstaller 2.0 を使用していますが、これは私のコンピュータでは問題なく動作しますが、exe を別のコンピュータに転送すると動作しなくなります。PyInstaller 2.0 はかなり新しいため、ドキュメントが非常に少なく、発行元のドキュメントはかなり「不足」しています。

この件に関する発行元の情報は次のとおりです: (ドキュメントは最新ではないと思います。最初は Configure.py を使用するように書かれていますが、他のドキュメントでは 2.0 では Configure.py は不要であると書かれています)

--onefile ディストリビューションでは、データ ファイルは実行可能ファイル内にバンドルされ、実行時に C コードによって作業ディレクトリに抽出されます (ディレクトリ ツリーを再構築することもできます)。作業ディレクトリは、os.environ['_MEIPASS2'] によって最もよく見つかります。したがって、次の方法でこれらのファイルにアクセスできます。

os.path.join(os.environ["_MEIPASS2"], relativename))

初心者プログラマーの私には、それはまったく意味がわかりません。

出版社からの別の文書にはこう書かれています。

--onefile ディストリビューションでは、データ ファイルは実行可能ファイル内にバンドルされ、実行時に C コードによって作業ディレクトリに抽出されます (ディレクトリ ツリーを再構築することもできます)。作業ディレクトリは sys._MEIPASS によって最もよく見つかります。したがって、次の方法でこれらのファイルにアクセスできます。

os.path.join(sys._MEIPASS, relativename))

os.environ["_MEIPASS2"] でいろいろ試してみましたが、Python は os.environment["_MEIPASS2"] を理解していないようです。次のような結果が返されます:

>>> print os.environ["_MEIPASS2"]

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    print os.environ["_MEIPASS2"]
  File "C:\Python27\lib\os.py", line 423, in __getitem__
    return self.data[key.upper()]
KeyError: '_MEIPASS2'

sys._MEIPASS でも実験しました。そうです、Python は「モジュール」に属性「_MEIPASS」がないと応答します。

この時点で、頭が爆発しそうな気分です。PyInstaller の作者の努力には感謝していますが、ドキュメントは今まで見た中で最悪です。ファイルを exe にバンドルするのを手伝ってくれる人が必要です。.spec 関連のすべてが PyInstaller の以前のバージョンと混同してしまうので、PyInstaller 2.0+ を使いたいと思っています。

ちなみに、私はWin8 64ビットとPython 2.7.3を使用しています

助けてください!

ベストアンサー1

ああ、なんてことだ!この PyInstaller は、ちょっと私を困惑させました。前回の投稿がちょっと「不満げ」に聞こえたなら、ごめんなさい。とにかく、--onefile PyInstaller パッケージにファイルを含めようとしている人のために、これは私の場合はうまくいきました:

.py スクリプトにこれを含めます:

filename = 'myfilesname.type'
if hasattr(sys, '_MEIPASS'):
    # PyInstaller >= 1.6
    chdir(sys._MEIPASS)
    filename = join(sys._MEIPASS, filename)
elif '_MEIPASS2' in environ:
    # PyInstaller < 1.6 (tested on 1.5 only)
    chdir(environ['_MEIPASS2'])
    filename = join(environ['_MEIPASS2'], filename)
else:
    chdir(dirname(sys.argv[0]))
    filename = join(dirname(sys.argv[0]), filename)

名前を覚えていないオンライン上の誰かに感謝します。(遅くなってごめんなさい、疲れています!)

次に、PyInstaller2.0を使用している場合は、cmdのpyinstaller-2.0ディレクトリから、以下を実行します。

pyinstaller.py --onefile myscriptsname.py

これにより、pyinstaller-2.0 ディレクトリに myscriptsname.spec ファイルが作成されます。exe も作成されますが、これは機能しません。後で更新されます。次に、その .spec を編集し、次の a.datas 行を追加します (data ではなく、datas であることに注意してください)。.spec ファイルに、参考のために少し追加しました。

a = Analysis(['ServerTimeTest_nograph.py'],
             pathex=['c:\\Python27\\pyinstaller-2.0'],
             hiddenimports=[],
             hookspath=None)
a.datas += [('myfilesname.type','C:\\path\\to\\my\\file\\myfilesname.type','DATA')]
pyz = PYZ(a.pure)

さて、cmdに戻って実行します

pyinstaller.py --onefile myscriptsname.spec

これにより、/dist ディレクトリ内の .exe が更新されます。

もっと良い方法や、もっときれいな方法があるかもしれませんが、私にとってはこれでうまくいきました!

おすすめ記事