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 が更新されます。
もっと良い方法や、もっときれいな方法があるかもしれませんが、私にとってはこれでうまくいきました!