我正在尝试使用包含 pandas 和 numpy 的 cx_Freeze 创建 Python 3.6 可执行文件。我使用的是 Python 3.6.5 和使用 virtualenvwrapper 创建的虚拟环境。我在 Windows 10 上进行开发。cx_Freeze 版本是 5.1。Pandas 版本是 0.23.4。
我的setup.py如下所示:
import os from cx_Freeze import setup, Executable PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__)) os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6') os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6') executables = [Executable("main.py", base=base)] packages = ["idna", "os", "numpy","importlib", "pandas"] options = { 'build_exe': { 'packages':packages, 'include_files':[ os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'sqlite3.dll'), ], }, } setup( name = "MyScript", options = options, version = "0.1", description = 'Placeholder desc', executables = executables )
请注意,我手动设置了环境变量,因为在构建过程中找不到它们,因此我必须手动将 DLL 移动到 virtualenv 文件夹。
脚本如下:
import numpy as np import pandas as pd import tkinter as tk root = tk.Tk() root.mainloop()
如果我注释掉import pandas as pd,一切都会正常。如果我添加 pandas 导入,我会收到以下错误:
import pandas as pd
C:\path\to\project\build\exe.win-amd64-3.6>MyScript.exe Traceback (most recent call last): File "C:\path\to\Envs\MyEnv\lib\site-packages\cx_Freeze\initscripts\__startup__.py", line 14, in run module.run() File "C:\path\to\Envs\MyEnv\lib\site-packages\cx_Freeze\initscripts\Console.py", line 26, in run exec(code, m.__dict__) File "MyScript.py", line 2, in <module> File "C:\path\to\Envs\MyEnv\lib\site-packages\pandas\__init__.py", line 23, in <module> from pandas.compat.numpy import * File "C:\path\to\Envs\MyEnv\lib\site-packages\pandas\compat\__init__.py", line 32, in <module> from distutils.version import LooseVersion File "C:\path\to\Envs\MyEnv\lib\distutils\__init__.py", line 17, in <module> real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ('', '', imp.PKG_DIRECTORY)) File "C:\path\to\Envs\MyEnv\lib\imp.py", line 245, in load_module return load_package(name, filename) File "C:\path\to\Envs\MyEnv\lib\imp.py", line 217, in load_package return _load(spec) File "<frozen importlib._bootstrap>", line 683, in _load AttributeError: 'NoneType' object has no attribute 'name'
我在网上看到了很多论坛和堆栈溢出问题(实际上我不得不修复很多错误才能到达这里)但我不知道 cx_Freeze 缺少什么。
我卸载并重新安装了 pandas,卸载了 cx_Freeze 并尝试安装以前的版本(安装失败,但这是另一个 SO 问题)。我实际上尝试了 pyinstaller 和 py2exe,但错误太多,而且不太详细(因此更难修复),所以我放弃了除了 cx_Freeze 之外的任何东西来创建可执行文件。
有人可以帮忙吗?
在使用 cx_Freeze 打包包含 pandas 和 numpy 的脚本时,你遇到的问题可能与依赖项的动态加载和环境配置有关。以下是逐步解决问题的方法:
cx_Freeze
pandas
numpy
确保以下模块和版本相互兼容: - Python 3.6.5 (已满足) - cx_Freeze 5.1 (推荐最新版本,可能是 6.x) - pandas 0.23.4 - numpy
Python 3.6.5
cx_Freeze 5.1
pandas 0.23.4
如果版本兼容问题不确定,可以尝试升级到更高版本的 pandas 和 numpy。
TCL/TK
你已经手动设置了 TCL_LIBRARY 和 TK_LIBRARY,这是正确的。不过,为了避免路径问题,建议动态检测并设置这些路径:
TCL_LIBRARY
TK_LIBRARY
import sys import os from cx_Freeze import setup, Executable PYTHON_INSTALL_DIR = os.path.dirname(sys.executable) # 自动获取路径 os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6') os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')
setup.py
cx_Freeze 的 build_exe 选项可能需要额外的配置。以下是改进的配置:
build_exe
from cx_Freeze import setup, Executable import sys import os # 自动获取路径 PYTHON_INSTALL_DIR = os.path.dirname(sys.executable) os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6') os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6') # 设置 base base = None if sys.platform == "win32": base = "Win32GUI" # 如果使用控制台应用,则改为 None # 包含的依赖项 packages = ["os", "numpy", "pandas", "tkinter"] # 构建选项 options = { "build_exe": { "packages": packages, "include_files": [ os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), ], "excludes": ["tkinter.ttk"], # 如果不需要 ttk,可以排除它 } } # 主程序入口 executables = [ Executable("main.py", base=base) ] setup( name="MyScript", version="0.1", description="Sample application", options=options, executables=executables )
pandas 和 numpy 使用 C 扩展模块,有时需要显式包含依赖项:
"build_exe": { ... "includes": ["numpy.core._methods", "numpy.lib.format"], }
从错误栈中可以看到 distutils 和虚拟环境的冲突。确保在虚拟环境中运行以下命令重新安装模块:
distutils
pip install cx_Freeze==5.1 pip install pandas==0.23.4 numpy
然后清理 build 文件夹后重试:
build
python setup.py build
如果问题依然存在,可能需要手动包含 pandas 动态库文件。通过以下方式查看缺失的依赖:
ldd build/exe.win-amd64-3.6/MyScript.exe
根据输出结果,将缺失的 .dll 文件复制到 build/exe.win-amd64-3.6 文件夹中。
.dll
build/exe.win-amd64-3.6
运行生成的 .exe 文件。如果问题解决,可以看到正常的 tkinter 窗口。如果仍有问题,请尝试更高版本的 cx_Freeze 或切换到 pyinstaller,最新版本提供了更好的动态加载支持。
.exe
tkinter
pyinstaller
如果遇到新的错误或仍无法解决,请提供更新的错误信息,以便进一步帮助!