使用 python 3.7 PyQt5 和 cx_Freeze 创建可执行文件但 DLL 加载失败
Create executable with python 3.7 PyQt5 and cx_Freeze but DLL Failed to load
我通过 Anaconda 3 (Python 3.7) 和 Designer 使用 PyQt5 开发了一个 "not so simple" GUI。
我在程序中导入了 3 个不同的 .ui 文件。
当我 运行 cx_Freeze 时,一切 运行 都很好,我创建了 .exe。然后,我将 "Python" 文件夹中的 "platform" 文件夹复制到 cx_Freeze 创建的 "Build" 文件夹中。
但是,当我将它传递给另一台没有任何东西的机器时(没有 anaconda,没有 python,没有 cx_Freeze,什么都没有),应用程序没有 运行 .我得到:
ImportError: DLL load failed: The specified module could not be found
它发生在我的代码的第 10 行,即:
from PyQt5 import QtGui, QtWidgets
我的代码中的导入是:
from PyQt5 import QtGui, QtWidgets
import sys
import glob
import datetime
from matplotlib.backends.qt_compat import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
import numpy as np
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import design
import flex
import entry
design
、flex
和 entry
是 .ui 文件。它们都在最后包含这部分(不知道是否有帮助):
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
最后,安装文件我 运行 和 cx_Freeze:
import sys
from cx_Freeze import setup, Executable
import matplotlib
import numpy
# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {"packages": ["os", "matplotlib"], "includes": ["PyQt5", "atexit"], "excludes": ["tkinter"]}
# GUI applications require a different base on Windows (the default is for a
# console application).
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup( name = "Flexicounts",
version = "0.1",
description = "Flexicounts pour faire tes comptes facilement",
options = {"build_exe": build_exe_options},
executables = [Executable("flexicounts.py", base=base)])
看了很多,但是感觉没有"miracle"解决办法...
你能帮我冻结我的应用程序并使其在 "virgin machine" 上 运行 吗?
您可能面对 cx_Freeze 存储库的 Issue #504。在这种情况下,引用 marceloduarte 的评论:
The workaround is to copy python3.dll
to the directory where the executable was made. cx_Freeze copies python37.dll
, but does not copy python3.dll
. The vcruntime140.dll
may also have to be copied when it no longer exists on the system.
首先尝试手动将这些 DLL(您可以在包含 python.exe 的 python 安装目录中找到它们)复制到您的可执行文件的目录中。如果这解决了问题,您可以使用 build_exe_options
的 include_files
列表告诉 cx_Freeze 为您完成。按如下方式修改您的设置脚本:
import os
python_dir = os.path.dirname(sys.executable) # directory of your python installation
build_exe_options = {"packages": ["os", "matplotlib"],
"includes": ["PyQt5", "atexit"],
"include_files": [os.path.join(python_dir, "python3.dll"), os.path.join(python_dir, "vcruntime140.dll")],
"excludes": ["tkinter"]}
也许您需要复制更多 DLL,例如 msvcp140.dll
,或 Python 安装的 site-packages/PyQt5
目录(包括子目录)中存在的任何其他 DLL。
我最近遇到了类似的问题,版本如下:
python 3.6.6 x64
cx-Freeze==6.10
PyQt5==5.15.4
PyQt5-Qt5==5.15.2
PyQt5-sip==12.9.0
PyQt5-stubs==5.15.2.0
PyQtWebEngine==5.15.5
PyQtWebEngine-Qt5==5.15.2
症状:
cx_Freeze 包成功并且在我的机器上执行正常,因为(正如我稍后发现并在下面解释的那样)我在我的机器上安装了 Python 3.6 x64 并通过环境变量可见.
在另一台机器上,第一次 PyQt5 导入时包失败并出现完全相同的错误:
ImportError: DLL load failed: The specified module could not be found
然而,就我而言,所有必要的 dll 似乎都在正确的位置:
- cx_Freeze 似乎正确地将
python3.dll
和 python36.dll
放在可执行文件旁边。但是那里没有复制其他 dll(例如没有 vcruntime140.dll)
- 所有必要的 python 模块都已准备就绪,包括 PyQt5 及其所有 dll
有效的解决方案:
(我创建了一个cx_Freeze issue)
与相反,我不得不复制
python3.dll
(either from <cx_freeze_build_dir_target> or from python3.6.6 install dir ...)
(python36.dll works too but is much bigger)
进入以下文件夹:
<cx_freeze_build_dir_target>/lib/PyQt5/
相应的 cx_Freeze 设置配置将按以下方式将其添加到 include_files
列表中。
不幸的是,这不起作用,因为 cx_Freeze 有一种包含 python3.dll
的异常文件列表,并阻止通过 include_files
。因此,应该手动执行复制,在 完全安装脚本执行后...
# import pkgutil
from pathlib import Path
from glob import glob
import sys
# ... your stuff
#
includes_list = []
# your stuff
# ...
# pyqt5 force copy of pythonlib(s) into qt5 target dir
# may not work if you intend to zip pyqt5 ?
python_dir = Path(sys.executable).parent
python_dlls = [ Path(p) for p in glob(f"{python_dir.as_posix()}/python*.dll")]
pyqt_base_dir = Path("lib", "PyQt5")
# prepare cx_Freeze tuples (source file, target dir)
includes_list+= [ (p, pyqt_base_dir / p.name) for p in python_dlls ]
build_exe_options = {"packages" : ..., # your packages
"includes" : ..., # yours
"include_files": includes_list,
"excludes" : ... # yours
}
我通过 Anaconda 3 (Python 3.7) 和 Designer 使用 PyQt5 开发了一个 "not so simple" GUI。 我在程序中导入了 3 个不同的 .ui 文件。
当我 运行 cx_Freeze 时,一切 运行 都很好,我创建了 .exe。然后,我将 "Python" 文件夹中的 "platform" 文件夹复制到 cx_Freeze 创建的 "Build" 文件夹中。
但是,当我将它传递给另一台没有任何东西的机器时(没有 anaconda,没有 python,没有 cx_Freeze,什么都没有),应用程序没有 运行 .我得到:
ImportError: DLL load failed: The specified module could not be found
它发生在我的代码的第 10 行,即:
from PyQt5 import QtGui, QtWidgets
我的代码中的导入是:
from PyQt5 import QtGui, QtWidgets
import sys
import glob
import datetime
from matplotlib.backends.qt_compat import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
import numpy as np
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import design
import flex
import entry
design
、flex
和 entry
是 .ui 文件。它们都在最后包含这部分(不知道是否有帮助):
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
最后,安装文件我 运行 和 cx_Freeze:
import sys
from cx_Freeze import setup, Executable
import matplotlib
import numpy
# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {"packages": ["os", "matplotlib"], "includes": ["PyQt5", "atexit"], "excludes": ["tkinter"]}
# GUI applications require a different base on Windows (the default is for a
# console application).
base = None
if sys.platform == "win32":
base = "Win32GUI"
setup( name = "Flexicounts",
version = "0.1",
description = "Flexicounts pour faire tes comptes facilement",
options = {"build_exe": build_exe_options},
executables = [Executable("flexicounts.py", base=base)])
看了很多,但是感觉没有"miracle"解决办法...
你能帮我冻结我的应用程序并使其在 "virgin machine" 上 运行 吗?
您可能面对 cx_Freeze 存储库的 Issue #504。在这种情况下,引用 marceloduarte 的评论:
The workaround is to copy
python3.dll
to the directory where the executable was made. cx_Freeze copiespython37.dll
, but does not copypython3.dll
. Thevcruntime140.dll
may also have to be copied when it no longer exists on the system.
首先尝试手动将这些 DLL(您可以在包含 python.exe 的 python 安装目录中找到它们)复制到您的可执行文件的目录中。如果这解决了问题,您可以使用 build_exe_options
的 include_files
列表告诉 cx_Freeze 为您完成。按如下方式修改您的设置脚本:
import os
python_dir = os.path.dirname(sys.executable) # directory of your python installation
build_exe_options = {"packages": ["os", "matplotlib"],
"includes": ["PyQt5", "atexit"],
"include_files": [os.path.join(python_dir, "python3.dll"), os.path.join(python_dir, "vcruntime140.dll")],
"excludes": ["tkinter"]}
也许您需要复制更多 DLL,例如 msvcp140.dll
,或 Python 安装的 site-packages/PyQt5
目录(包括子目录)中存在的任何其他 DLL。
我最近遇到了类似的问题,版本如下:
python 3.6.6 x64
cx-Freeze==6.10
PyQt5==5.15.4
PyQt5-Qt5==5.15.2
PyQt5-sip==12.9.0
PyQt5-stubs==5.15.2.0
PyQtWebEngine==5.15.5
PyQtWebEngine-Qt5==5.15.2
症状:
cx_Freeze 包成功并且在我的机器上执行正常,因为(正如我稍后发现并在下面解释的那样)我在我的机器上安装了 Python 3.6 x64 并通过环境变量可见.
在另一台机器上,第一次 PyQt5 导入时包失败并出现完全相同的错误:
ImportError: DLL load failed: The specified module could not be found
然而,就我而言,所有必要的 dll 似乎都在正确的位置:
- cx_Freeze 似乎正确地将
python3.dll
和python36.dll
放在可执行文件旁边。但是那里没有复制其他 dll(例如没有 vcruntime140.dll) - 所有必要的 python 模块都已准备就绪,包括 PyQt5 及其所有 dll
有效的解决方案:
(我创建了一个cx_Freeze issue)
与
python3.dll
(either from <cx_freeze_build_dir_target> or from python3.6.6 install dir ...)
(python36.dll works too but is much bigger)
进入以下文件夹:
<cx_freeze_build_dir_target>/lib/PyQt5/
相应的 cx_Freeze 设置配置将按以下方式将其添加到 include_files
列表中。
不幸的是,这不起作用,因为 cx_Freeze 有一种包含 python3.dll
的异常文件列表,并阻止通过 include_files
。因此,应该手动执行复制,在 完全安装脚本执行后...
# import pkgutil
from pathlib import Path
from glob import glob
import sys
# ... your stuff
#
includes_list = []
# your stuff
# ...
# pyqt5 force copy of pythonlib(s) into qt5 target dir
# may not work if you intend to zip pyqt5 ?
python_dir = Path(sys.executable).parent
python_dlls = [ Path(p) for p in glob(f"{python_dir.as_posix()}/python*.dll")]
pyqt_base_dir = Path("lib", "PyQt5")
# prepare cx_Freeze tuples (source file, target dir)
includes_list+= [ (p, pyqt_base_dir / p.name) for p in python_dlls ]
build_exe_options = {"packages" : ..., # your packages
"includes" : ..., # yours
"include_files": includes_list,
"excludes" : ... # yours
}