Windwos下打包PyQt5应用程序
打包Python2.7下使用PyQt5的应用程序。
工具
cx_freeze
源代码
一个简单的PyQt程序:
[python collapse=”true”]
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Form(QMainWindow):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
widget = QWidget(self)
nameLabel = QLabel(“Name:”)
self.nameLine = QLineEdit()
self.submitButton = QPushButton(“Submit”)
buttonLayout1 = QVBoxLayout()
buttonLayout1.addWidget(nameLabel)
buttonLayout1.addWidget(self.nameLine)
buttonLayout1.addWidget(self.submitButton)
self.submitButton.clicked.connect(self.submitContact)
mainLayout = QGridLayout()
#mainLayout.addWidget(nameLabel, 0, 0)
mainLayout.addLayout(buttonLayout1, 0, 1)
widget.setLayout(mainLayout)
self.setCentralWidget(widget)
self.setWindowTitle(“Hello Qt”)
def submitContact(self):
name = self.nameLine.text()
if name == “”:
QMessageBox.information(self, “Empty Field”,
“Please enter a name and address.”)
return
else:
QMessageBox.information(self, “Success!”,
“Hello ”%s”!” % name)
if __name__ == ‘__main__’:
import sys
app = QApplication(sys.argv)
screen = Form()
screen.show()
sys.exit(app.exec_())
[/python]
步骤
使用cxfreeze-quickstart向导生成的setup.py文件。
[python]
from cx_Freeze import setup, Executable
# Dependencies are automatically detected, but it might need
# fine tuning.
buildOptions = dict(packages = [], excludes = [])
import sys
base = ‘Win32GUI’ if sys.platform==’win32′ else None
executables = [
Executable(‘basic01.py’, base=base)
]
setup(name=’basic01′,
version = ‘1.0’,
description = ”,
options = dict(build_exe = buildOptions),
executables = executables)
[/python]
运行时如下,提示缺少atexit模块,需要修改setup.py。
[python highlight=”8″]
from cx_Freeze import setup, Executable
# Dependencies are automatically detected, but it might need
# fine tuning.
buildOptions = dict(
packages = [],
excludes = [],
includes = [‘atexit’])
import sys
base = ‘Win32GUI’ if sys.platform==’win32′ else None
executables = [
Executable(‘basic01.py’, base=base)
]
setup(name=’basic01′,
version = ‘1.0’,
description = ”,
options = dict(build_exe = buildOptions),
executables = executables)
[/python]
再运行,提示找不到Qt Platform plugin “windows”。
经过漫长的查找,终于知道是缺少libEGL.dll文件。从Qt\bin目录下拷贝即可。
参见 //stackoverflow.com/questions/20495620/qt-5-1-1-application-failed-to-start-because-platform-plugin-windows-is-missi
如是,可以运行程序。
还需要加入VS编译器的运行时环境,便于在其他机器上运行。因为许可的关系,cx_freeze没有将MSVC的运行时环境dll打包在内,如果可以分发这些dll,则加入include_msvcr即可。当然要是没有许可的话,就得附上Python和Qt各自的msvcr安装包。
[python highlight=”9″]
from cx_Freeze import setup, Executable
# Dependencies are automatically detected, but it might need
# fine tuning.
buildOptions = dict(
packages = [],
excludes = [],
includes = [‘atexit’],
include_msvcr = True)
import sys
base = ‘Win32GUI’ if sys.platform==’win32′ else None
executables = [
Executable(‘basic01.py’, base=base)
]
setup(name=’basic01′,
version = ‘1.0’,
description = ”,
options = dict(build_exe = buildOptions),
executables = executables)
[/python]
最后生成的目录如下图所示,整个目录有50MB,即便用7z打包也有13MB,Qt5的dll太大了。
压缩DLL
使用upx压缩dll和exe文件后,共24MB。
//upx.sourceforge.net/