cx_Freezeからpy2exeに移行作業したときのメモ

py2exeはencodings以下を手厚く入れてくれる。

cx_Freezeの場合、encodings以下のモジュールについて必要なものは、おのおの指定する必要があった。
py2exeはencodings以下をどっちゃり入れてくれる。

py2exeでPyQtで画像を扱う場合の注意

前エントリで紹介したように、PyQtで画像ファイルを扱っている場合には、
imageformats以下にあるQtのプラグインを配置しなければならない。
cx_FreezeでPyQtアプリを固めた時に詰まったところ - グニャラくんのグニャグニャPython備忘録


が、僕はココでかなり詰まった。
imageformats以下のファイルを配置しているのにロードしてくれないのだ!
しかも、コンソールには以下のようなエラーが大量発生する。んぺぺ!

QObject::moveToThread: Current thread(xxxxxxxx) is not the object's thread(xxxxxxxx).
Cannot move to target thread (xxxxxxxx)

長い間試行錯誤した挙句、原因が判明。
'bundle_files' = 3にすること!
あああああああ

py2exe実行時に、msvcp90.dllがねーよ!といわれる

C:\Python26に、msvcp90.dll/msvcm90.dll/msvcr90.dllの3つのファイルを放りこんだらpy2exeが実行できた。

py2exeで作ったバイナリが、他の環境で「初期化に失敗」だの「構成が正しくない」だのエラーを出す

Visual C++のCランタイムライブラリ(さっきのmsvcp90.dllみたいなの)のロードに失敗しているため。
手っ取り早いのは、以下のファイルをインストールすること。


しかし、僕も正直

Pythonをインストールするのが面倒なのでexeに変換したのに、わざわざ別のものインストールさせたら手間かわんねーじゃん?
http://d.hatena.ne.jp/AMENOHI/20090202/1233575464

ってな気分です。


cx_Freezeの場合には、msvcp90.dllを配布物の中に入れてくれます。
py2exeの場合には、Windowsの標準システムDLLかどうかを判定するロジックによって
依存DLLを配布するかしないかを判断する関数があり、
その関数による判定の結果、msvcp90.dllは配布されません。


というわけで、判定関数をのっとります。

origIsSystemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(pathname):
  if os.path.basename(pathname).lower() in ('msvcp90.dll'):
    return 0
  return origIsSystemDLL(pathname)
py2exe.build_exe.isSystemDLL = isSystemDLL

これでmsvcp90.dllはdistディレクトリの中に放り込まれたのでした。わーい!


んでも、カレントディレクトリにmsvcp90.dllがあったからといって、
それが使われるわけじゃないらしいんですね。
Microsoft.VC90.CRT.manifest」ってファイルをexeのカレントディレクトリに放りこめばいいのかもしれないし、
setup()のconsole引数に、

{'other_resources': [(24, 1, manifest)]}

的なものを指定して、そのmanifest中でVCのランタイムを指定すればいいのかもしれない。
まだ調査できてないし理解も出来ていない。調査できたら追記すると思う。