打包 (仅 --onefile)
请大家仔细阅读这篇帖子并帮我一下。
我想用pyinstaller创建一个--onefile
的可执行文件。
我在开发环境中有这些:
- windows 8.1 x64
- Qt 5.2.1
- Python 27
- PyQt5.2.1(用Visual Studio 2012构建的)
- Visual Studio 2012
- PyInstaller 2.1
- pyWin32
在部署环境(虚拟机)中有这些(作为一个干净的虚拟机):
- windows 8 x64
- vcredist_x64 2012
这是我想要构建的简单Python程序:
#main.py
import sys
from PyQt5.QtWidgets import QApplication, QPushButton
app = QApplication(sys.argv)
win = QPushButton("Hello World!")
win.show()
sys.exit(app.exec_())
#------------------------------------------------
好的,当我用--onedir
(pyinstaller main.py
)构建时,它在开发环境和部署环境中都能正常工作。
但是当我用--onefile
(pyinstaller -F main.py
)构建时,它在开发环境中可以正常工作,但在部署环境中却不行。
并且出现了这个错误:
这个应用程序启动失败,因为找不到或无法加载 Qt平台插件“windows”。
可用的平台插件有:minimal, offscreen, windows。
重新安装应用程序可能会解决此问题。
我哪里出错了?或者这个构建有什么问题?
根据这个错误,它找不到在临时文件夹中_MEIxxxxx
文件夹里的qt5_plugins
文件夹。
或者,你认为问题出在sys
模块上吗?如果是的话,我该怎么做?
谢谢你的提前回复。
更新:
我应该说在构建时我收到了这些警告和错误:
1024 WARNING: 找不到文件 C:\Python27\msvcp90.dll 1024 WARNING: 程序集不完整 1026 ERROR: 找不到 amd64_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_none
更新2:
我手动将msvcp90.dll
和msvcm90.dll
添加到c:\Python27
中,这些警告和错误就解决了。
更新3:
qt.conf:
[Paths]
Plugins = qt5_plugins
main.spec:
# -*- mode: python -*-
a = Analysis(['main.py'],
pathex=['D:\\hello2'],
hiddenimports=['sip', "PyQt5.QtCore", "PyQt5.QtGui", "PyQt5.QtWidgets"],
hookspath=None,
runtime_hooks=None)
pyz = PYZ(a.pure)
plugins = [("qt5_plugins/platforms/qwindows.dll",
"C:\\Qt\\Qt5.2.1\\5.2.1\\msvc2012_64\\plugins\\platforms\\qwindows.dll", "BINARY")]
data = [
("qt.conf", "qt.conf", "DATA")
]
exe = EXE(
pyz,
a.scripts,
a.binaries + plugins,
a.zipfiles,
a.datas + data,
name='main.exe',
debug=False,
strip=None,
upx=True,
console=True
)
用pyinstaller
自动生成的qt5_plugins
包含平台插件,我认为不需要手动添加作为额外库。
4 个回答
出现 application failed to start because ... platform plugin "windows"
这个错误,可能是因为使用了 UPX 压缩。
如果你在用 PyInstaller 并且设置了 UPX 来打包,那么你需要手动把压缩过的 qwindows.dll
文件替换成未压缩的版本。
未压缩的版本可以在这里找到:
C:\Python34\Lib\site-packages\PyQt5\plugins\platforms\qwindows.dll
把上面的文件粘贴到 PyInstaller 的临时文件夹里,这个文件夹的路径大概是:
C:\Users\JohnSmith\AppData\Roaming\pyinstaller\bincache01_py34_64bit\qt5_plugins\platforms\
然后重新运行你的 PyInstaller 命令。
我找到了解决办法,完成了工作:
在干净的虚拟机上运行exe时出现了一些错误,导致程序无法正常运行:
- 使用
if __name__ == "__main__":
这行代码 - 把我们的目录添加到
PATH
环境变量中 手动添加我们需要的文件夹或文件
比如说:
- 我们的 .qml 文件或图片文件夹
- 用于使用 qml 文件的 qml 目录等等
这是一个示例:
main.py
import sys
import os
from PyQt5.QtWidgets import QApplication, QPushButton
# from PyQt4.QtGui import QPushButton, QApplication
if getattr(sys, 'frozen', False):
FullDirectory = os.path.join(os.environ.get("_MEIPASS", sys._MEIPASS))
os.environ['PATH'] = FullDirectory
# QApplication.addLibraryPath(FullDirectory)
else:
FullDirectory = os.path.dirname(os.path.abspath(__file__))
if __name__ == "__main__":
app = QApplication(sys.argv)
win = QPushButton("Hello World!")
win.show()
sys.exit(app.exec_())
这是一个示例的规格文件:
main.spec
# -*- mode: python -*-
import os
import platform
import sys
sys.path.append("")
a = Analysis(['main.py'])
pyz = PYZ(a.pure)
exename = 'main.exe'
if "64" in platform.architecture()[0]:
exename = 'main_x64.exe'
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name=os.path.join('dist', exename),
debug=False,
strip=None,
upx=True,
console=True
)
希望这些对你有帮助。
感谢大家。
这可能是和其他人尝试在OSX上构建的内容重复的问题吗?
每次我在Linux上用pyinstaller构建PyQt4的时候,都不能直接用pyinstaller命令和参数来构建源代码文件。我必须先生成一个spec文件,然后对它进行修改,最后再用这个修改过的spec文件来构建。
看起来你在构建过程中没有把需要的Windows系统文件和插件文件一起打包。这些文件需要手动添加到你的spec文件中,以告诉它们要作为额外的库被收集,同时还需要一个修改过的qt.conf文件,设置插件的位置为相对路径([Paths]\nPlugins = qt5_plugins"
)。
我手边没有Windows系统来给你展示一个具体的spec文件,但我可以给你一个在我Mac上接近的例子:
a = Analysis(
['/path/to/my/script.py'],
# Path to extra pythonpath locations
pathex=['/path/to/my/script'],
# Extra imports that might not have been auto-detected
hiddenimports=["PySide", "PySide.QtCore", "PySide.QtGui"],
hookspath=None,
runtime_hooks=None
)
pyz = PYZ(a.pure)
# Binary files you need to include in the form of:
# (<destination>, <source>, "<TYPE>")
plugins = [
(
"qt4_plugins/imageformats/libqjpeg.dylib",
"/usr/local/Cellar/qt/4.8.1/plugins/imageformats/libqjpeg.dylib",
"BINARY"
),
(
"qt4_plugins/phonon_backend/libphonon_qt7.dylib",
"/usr/local/Cellar/qt/4.8.1/plugins/phonon_backend/libphonon_qt7.dylib",
"BINARY"
)
]
# Data files you want to include, in the form of:
# (<destination>, <source>, "<TYPE>")
data = [
("qt.conf", "qt.conf", "DATA")
]
exe = EXE(
pyz,
a.scripts,
a.binaries + plugins,
a.zipfiles,
a.datas + data,
name='script',
debug=False,
strip=None,
upx=True,
console=False,
resources=['qt.conf']
)
# This BUNDLE part is only relevant on a MAC
app = BUNDLE(
exe,
name='script',
icon=None
)
我首先使用utils/makespec.py
生成一个“骨架”spec文件,这个文件包含了一些初始选项,然后我会对它进行修改。接着,我用pyinstaller
来处理这个spec文件。
你也可以在这里查看一些其他的参考资料,虽然还是在OSX上:https://github.com/hvdwolf/pyExifToolGUI/blob/master/MacOSX/pyexiftoolgui.spec
我第一次尝试使用pyinstaller的时候,收到了缺少“windows”的提示。
我查看了很多“解决方案”,尝试了各种方法,最后通过把C:\Python34\Lib\site-packages\PyQt4\plugins\platforms里的qwindows.dll文件放到应用程序的目录(dist)和qt4_plugins\platforms文件夹里解决了这个问题。(我手动创建了platforms文件夹,而pyinstaller创建了qt4_plugins文件夹)
虽然这不是创建qt.conf文件那样优雅,但至少让应用程序能正常工作了。
我还要补充一下,我使用的是Windows 7,python 3.4和PyQt4。