最近は、ちょっとしたアプリをお手軽なVCではなくpythonで作っている。
pythonでexeを作る場合に使うモジュールが、pyinstall か py2exe。
たしか、記憶では何年か前までpy2exeはpython2.7系でしか使えなかったが、最近はpython3.7以降でも使える。
ちなみに、pyinstallは簡単にexe化できるのだけれど、出来たexeの起動が遅かったり、データが重かったりと、ちょっとした使いづらさがあるので個人的にはexe化するならpy2exe一択。
pyinstall や py2exeでのexe化関連の記事は調べれば大量に出てくるので、そこは他人にお任せするとして、
困ったのはexe化したあとで動かなかった場合。
今まで幾つか経験していて、大半はpySide2 (pyQt)周りでのImport Errorが結構多かったと思う。
要するにpy2exeが必要なDLLなどをコピーしきれずに起動しなかったりエラーが起きるパターンが多いって感じかな?
exe化した後で動かなかった場合は自分で地道にエラー内容からデバッグしたりするのだけど、なかなか分らずスタックすることがしばしば。
ここ数日もエラーでなぜか動かず、ずーっと困っていたw、
つかオレ、デバッグへたくそすぎだろw
で、ネットでエラー内容を調べても、なかなか原因を解説しているサイトは少ない。
というか、ほとんどない。
もしかしたらVisualStudioでpythonのexe作ったほうがデバッグいいのかな・・・。
まぁ、なので、今まで経験したエラーと対処法を少しだけメモしておく。
たぶん役に立つ・・・はず。
エラー例1、PySide2とshiboken2のバージョンが違っていた
単純に使っていた、pySide2 と shiboken2 のバージョンが食い違っていたことが原因だった。
なので、対処法はpipを使って両方ともにバージョンアップする。
pipはこんな感じで。
C:\Users\<UserName>\AppData\Local\Programs\Python\Python37\python.exe -m pip install –upgrade PySide2
C:\Users\<UserName>\AppData\Local\Programs\Python\Python37\python.exe -m pip install –upgrade shiboken2
流石にpipの説明は必要なかったかw
ついでにpipとかpy2exeもバージョンアップしておくといいかも。
エラー例2、setup.pyの設定
エラーというよりもpy2exeに必要なsetup.pyの設定でモジュールを含める設定になってないとpyside2周りのモジュールが一切コピーされずエラーが起きる。
個人的なレシピは、必要ファイルをまとめつつzipで圧縮する方法
こんな感じ。
まぁ、あくまで参考程度で!
# -*- coding: utf-8 -*-
from distutils.core import setup
import py2exe
option = {
"compressed": 1,
"optimize": 2,
"bundle_files": 3
}
include_data = [
# ('フォルダ名', ['コピーファイル 相対パス'])
('images', [
"images/icon.png",
"images/checkbox_checked.png",
"images/checkbox_checked_disabled.png",
"images/checkbox_unchecked.png",
"images/checkbox_unchecked_hover.png",
"images/x.png",
"images/remove.png",
"images/filebrowser.png"]),
('platforms', ["platforms/qwindows.dll"]),
('styles', ["styles/qwindowsvistastyle.dll"]),
('', ["ffprobe.exe", "ffmpeg.exe", "style.qss"])
]
setup(
options={
"py2exe": option
},
windows=[{
"script": "sj_video_conv.py",
"icon_resources": [
(1, "icon.ico")
],
"name": "SJ Video Conv",
"version": "1.0.8.0",
"description": "",
"company_name": "",
"url": "http://"
}],
data_files=include_data,
zipfile="lib\\libs.zip"
)
この方法で今のところさほど困ってはいない。
実はpyinstall並みにファイル容量が重くなってしまうんだけど、
不足ファイルがでてインポートエラーがあった場合、調べるのがメンドクサイのでこの方法でやってる。
エラー例3、パスが通ってない
これは、shotgun のAPIを利用した際にshotgunapiの中でcacerts.txtまでのパスが通ってなかったことが原因だった。
具体的には__ini__.pyの以下の場所。
CA_CERTS = os.path.join(os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt")
この状態でexe化するとos.path.abspath(__file__)の部分が、.zip内のパスとして扱われるのでパスが通らない。
ここを
base = os.path.dirname(os.path.abspath(__file__)).split("\\")
base = base[0 : len(base) - 4]
CA_CERTS = os.path.join("\\".join(base), 'cacerts.txt')
こんな感じで無理やりzipの上の階層にさかのぼって参照するようにした。
書き方はもっといい方法があるはずw
もしくはzipにファイルを含ませるのもありかも。
実はこの手のちょっとしたパス切れってたまにあって、ちょくちょく手で直すようにしてるw
まぁ、こういう事例もあるよって覚えておくといいかも。
特にos.path.abspath(__file__)が出てきたら、ちょっと注意かな。
エラー例4、msvcp90.dllが無くて動かない
これはpython2.7系だったときに経験したエラーなんだけど、
どうもmsvcp90.dllというランタイムが無く動かなかった場合があった。
このDLLは名前からしてVC++関連のランタイムか何かだと思われる。
これも前述通りでpy2exeが必要なdllをコピーしきれていないってことだと思う。
対処方は、単純に msvcp90.dll をdistディレクトリにコピーする。
msvcp90.dll自体は Microsoft Visual C++のランタイムを入っている環境であれば検索すれば出てくる(はず)
対処したのが何年か前で詳細を覚えてないやw
エラー例5、必要なPySide2関連のDLLが無い。
まずこちらのエラー。
This application failed to start becase no Qt platform plugin
could be initialized. Reinstalling the application may fix this
problem.
文字通りで、プラグインの初期化に失敗してエラーがでているのだが、
原因は qwindows.dll (windowsの場合) と qwindowsvistastyle.dll が不足していたこと。
この2つのDLLは、PySide2のモジュールディレクトリ内にある。
モジュールディレクトリは、
C:\Users\<ユーザー名>\AppData\Local\Programs\Python\Python37\Lib\site-packages\PySide2
に入っているので検索すると出てくる。
このDLLをビルドするときにdistへコピーする。
qwindows.dllとqwindowsvistastyle.dllをsetupと同階層などにコピーしておいて、
setup.py内で
include_data = [
# ('フォルダ名', ['コピーファイル 相対パス'])
('platforms', ["platforms/qwindows.dll"]),
('styles', ["styles/qwindowsvistastyle.dll"])
]
みたいな感じで書いておくと便利。
つぎ、
最近起きたエラーで、vcruntime140_1.dll というVCのランタイムが無かったエラー。
これ厄介だったのが、出る環境と出ない環境があったこと。
おそらくVCのランタイムが何かのタイミングでインストールされた環境と無い環境の差が出てるんだと思う。
エラー文は以下のような感じ。
PySide2/init.py: Unable to import shiboken2 from C:\Users\<UserName>\Desktop\dist\lib\libs.zip
Traceback (most recent call last):
File “sim_job.py”, line 5, in
File “main.pyc”, line 14, in
File “sim_job_ui.pyc”, line 11, in
File “PySide2__init__.pyc”, line 120, in
File “PySide2__init__.pyc”, line 70, in setupQtDirectories File “shiboken2__init_.pyc”, line 27, in
File “”, line 10, in
File “”, line 8, in __load
ImportError: (DLL load failed: 指定されたモジュールが見つかりません。) ‘C:\Users\<UserName>\Desktop\dist\lib\shiboken2.shiboken2.pyd’
実はこれ、何のDLLが不足しているのか、所見ではまったくわからず、
必要そうなDLLを手あたり次第コピーしてようやく不足していたものを特定した。
vcruntime140_1.dll はPySide2モジュールディレクトリ内にあるので検索すれば出てくる。
他にもVCのランタイムがあるので、もしかしたら環境によっては不足しているDLLが違うかもしれない。
わからなかったら、とりあえず必要そうなDLL全部コピーで!!
なぜ、必要なDLLがコピーされないのか?って考えると、py2exeが単純に必要なDLLやファイルを拾え切れてないんだと思う。必要なものは自分でコピーしろってことなんだろうな。
という感じっす!!
以上pythonのpy2exeでexe化した後、pyside周りとかでエラーがでた場合の対処のメモでした!!
まぁ何かの参考になればいいかな~~。
Pingback: python py2exe のsetupのオプション(キー)でexeのプロパティに反映されるのはなにか? – SAKAIDEN