cx_FreezeでPyQtアプリを固めた時に詰まったところ

cx_Freezeにて、setup.pyで設定を行い場合の注意

たとえば、以下のような要件があったとする。
sipモジュールを追加で読み込みたい。
・アプリケーションにアイコンを指定したい。

cx_Freezeのドキュメントでは、
以下のような書き方でOKなように読める。

import sys
from cx_Freeze import setup, Executable

base = None
if sys.platform == 'win32':
  base = 'Win32GUI'

exe = Executable(script = 'app.py',
                 includes = ['sip'],
                 icon = 'app.ico',
                 base = base)
setup(name = 'myapp',
      version = '0.0.1',
      description = 'my test application',
      executables = [exe],
)

でも、これだとNG。


以下の記法でうまくいった。

import sys
from cx_Freeze import setup, Executable

base = None
if sys.platform == 'win32':
  base = 'Win32GUI'

exe = Executable(script = 'app.py',
                 icon = 'app.ico',
                 base = base)

setup(name = 'myapp',
      version = '0.0.1',
      description = 'my test application',
      executables = [exe],
      options = {
        'build_exe': {
          'includes': ['sip'],
        },
      })

cx_Freezeで固めたバイナリでのみ、画像が表示できない

詳しくは、

を参照のこと。

たとえば、imageformats/qjpeg4.dllの配布も行いたい場合、
cx_Freezeのoptionsはこうなる。

      options = {
        'build_exe': {
          'includes': ['sip'],
          'include_files': [('imageformats/qjpeg4.dll',
                             'imageformats/qjpeg4.dll')],
        },
      }

僕はめんどうくさがりなので、
標準ライブラリパスであるアプリケーションディレクトリにimageformatsをコピーすることによって回避した。

cx_FreezeとPyQt4で生じる問題

cx_Freezeは、Windowsインストーラパッケージとして
msiファイルを生成する。
msiファイルを生成する際、Pythonのmsilibモジュールを使っているのだが、
複数個のドットが含まれるファイル名のパッケージングで不具合がある。


よって、PyQt4.QtCore.pydとPyQt4.QtGui.pydのパッケージングに問題が生じた。
上記issue1128に投稿されたパッチを適用して解決した。

cx_Freezeでbase = 'Win32GUI'にした場合に、sys.exit()でエラーダイアログが出る問題

項目名のとおりで、sys.exit(0)なんかを実行してしまうとエラーダイアログが出る。
cx_Freezeのsource/bases/Win32GUI.cを読んでみると、
SystemExit例外をハンドルしている部分でエラーダイアログが出ているようだ。

    PyErr_Fetch(&type, &value, &traceback);
..(snip)..
    if (PyInt_Check(value))
        exitCode = PyInt_AsLong(value);
    else {
        message = StringifyObject(value, &valueStr);
        MessageBox(NULL, message, "cx_Freeze: Application Terminated",
                MB_ICONERROR);
        Py_XDECREF(valueStr);
        exitCode = 1;
    }

んだもんで、試しに、

raise SystemExit, 0

としてもやっぱりエラーダイアログが出る。もう知らん!(不貞寝

まとめ

cx_Freezeは現在メンテされていない、とどこかのMLアーカイブで読んだし、
pyInstallerはsvn headを使えと言ってるし、
やはり素直にWindows版バイナリ生成はpy2exeを使うか…