记录一下关于使用cx_Freeze 打包python项目为.exe应用中遇到的问题以及解决方法
首先说一下我的环境是win10系统,python版本为3.115,PyCharm版本为2023.2.1(内部版本号#PY-232.9559.58)
先别看网上其他人的教程,直接去官网看,按着流程走,一切就绪后,开始配置setup.py文件,先按着官方例子试了一下如下:
import sys
from cx_Freeze import setup, Executable
# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {
"excludes": ["tkinter", "unittest"],
"zip_include_packages": ["encodings", "PySide6"],
}
# base="Win32GUI" should be used only for Windows GUI app
base = "Win32GUI" if sys.platform == "win32" else None
setup(
name="guifoo",
version="0.1",
description="My GUI application!",
options={"build_exe": build_exe_options},
executables=[Executable("guifoo.py", base=base)],
)
其中 excludes 要排除的模块名称, 可以使用逗号分隔列表
配置好以后在PyCharm 里 Alt + F12 打开终端然后运行命令:
python setup.py build
这时候会打包成功,但运行.exe文件后会提示缺少库 Pyside6登报错信息,这是第一个错误。经过一番尝试,暂时不明白为啥zip_include_packages这种方式会缺失这个库,既然这种方式不行,也不头铁,尝试第二种写法 'packages': [],表示打包所有除excludes外的依赖库
build_options = {
'packages': [],
'excludes': ["setuptools", "tk8.6",
"tkinter", "Cython", "fbs_runtime",
"lib2to3", "multiprocessing", "packaging",
"pkg_resources", "test", ],
}
打包完后会发现包内少了一些依赖的文件,要想将这些文件也打包进去必须使用include_files,最终setup.py文件如下:
from cx_Freeze import setup, Executable
import sys
import global_var
'''运行`python setup.py build`即可打包'''
if __name__ == "__main__":
# Debug = 0 # 是否debug模式
Debug = global_var.get_value('Debug')
VERSON = "0.1"
# 需要包含的资源目录和文件
if sys.platform == 'win32':
bin_files = "bin/win32"
else:
bin_files = "bin/linux" if sys.platform == 'linux' else "bin/darwin"
include_files = [
(bin_files, "lib/" + bin_files),
("GUI", "lib/GUI"),
("global_var.py", "lib/global_var.py"),
("database", "lib/database"),
("Resources", "lib/Resources"),
("mediaplayer", "lib/mediaplayer"),
("video_clips", "lib/video_clips"),
("datainfo_api", "lib/datainfo_api"),
("material_center", "lib/material_center"),
("video_publishing", "lib/video_publishing"),
("operational_reference", "lib/operational_reference"),
]
build_options = {
'packages': [],
'excludes': ["setuptools", "tk8.6",
"tkinter", "Cython", "fbs_runtime",
"lib2to3", "multiprocessing", "packaging",
"pkg_resources", "test", ],
"include_files": include_files,
}
if Debug:
base = None
elif sys.platform == 'win32':
base = 'Win32GUI'
else:
base = None
executables = [
Executable('main.py', base=base, target_name='测试项目', icon="./icon.ico")
]
setup(name='测试项目',
version=VERSON,
description='测试打包',
options={'build_exe': build_options},
executables=executables,
)
其中Debug是我自己定义得全局变量,用来控制Debug或打包两种模式,lib/ 是指定打包目录
- 文件太大:在虚拟环境(virtualenvs)下打包,可以使得打包过程更纯净,减少不必要的库和依赖
所以需要配置IDE的虚拟环境后再尝试打包,如下图
,
将选项 改为cmd ,然后别忘记点应用.
这时候重新Alt + F12 会发现命令行前面多了一个(venv),说明切换成功了
参考资料如下,不过由于他是英文版的,我才啰嗦了这么多
让Pycharm的Terminal进入创建好的虚拟环境 - 知乎 (zhihu.com)
然后这次运行完后会出现报错,截图如下
经过搜索报错信息发现这篇文章error: Multiple top-level packages discovered in a flat-layout: [‘alf‘, ‘hidio‘].-CSDN博客
根据文章提示,
在setup.py中显示加入一行py_modules=[],:
setup(name='测试项目',
version=VERSON,
description='测试打包',
options={'build_exe': build_options},
executables=executables,
py_modules=[],
)
然后重新运行打包命令,这次不再出现报错,但运行exe后我又发现了两个问题:
一、路径问题
由于打完包后主程序exe文件和lib文件夹才是平级关系,所以这方面要格外注意,也就是说要比Debug环境多出一个层级lib,相关引用路径,如项目Resources资源文件的路径引用,前面也要多加个lib,同理其他地方也是如此
二、ffmpeg引用路径问题
由于项目之前单独安装ffmpeg库并配置了ffmpeg全局环境变量,也就是本质上最开始此项目调用ffmpeg其实是调用了电脑内其他路径的bin文件,而不是项目内,所以更改如下:
1.首先项目层级添加一个bin文件夹,然后将各版本需要的ffmpeg库文件copy到此目录下
2.删除环境变量相关ffmpeg配置,将引用路径改为对应bin文件夹,具体参考解决python调用 ffmpeg时 ‘ffmpeg‘ 不是内部或外部命令,也不是可运行的程序_ffmpeg' 不是内部或外部命令,也不是可运行的程序-CSDN博客
3.不喜欢程序调用ffmpeg 时出现的黑框的话,参考一下此篇文章
pyinstaller打包PySide2写的GUI程序,调用ffmpeg隐藏CMD控制台解决方案-CSDN博客
喜欢的话别忘记 点赞收藏,有什么问题也可以留言交流
以上属于本人原创,若有雷同属巧合,如有错误望指正,转载请标明来源和作者。by:清风明月cy