由于用户使用Python脚本的时候可能没有运行环境,所以需要打包。记录下碰到的问题。
安装 1 2 3 4 5 6 7 pip install --upgrade pyinstaller pip install https://github.com/pyinstaller/pyinstaller/tarball/develop pyinstaller -v
基本使用方法 Pyinstaller可以通过简单的命令进行python代码的打包工作,其基本的命令为:
1 pyinstaller -option xxx.py
选项
功能
-D, --onedir
Create a one-folder bundle containing an executable (default)
-F, --onefile
Create a one-file bundled executable.
高级使用方法 以一个多文件和目录的Python项目为例,项目文件包含:1.Python源代码文件;2.图标资源文件;3.其它资源文件。
1. spec文件生成 为了进行自定义配置的打包,首先需要编写打包的配置文件.spec文件。当使用pyinstaller -D/F xxx.py时候会生成默认的xxx.spec文件进行默认的打包配置。通过配置spec脚本,并执行pyinstaller xxx.spec 完成自定义的打包。
通过生成spec文件的命令,针对代码的主程序文件生成打包对应的spec文件
打开生成的spec文件,修改其默认脚本,完成自定义打包需要的配置。spec文件是一个python脚本,其默认的结构如下例所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 block_cipher = None a = Analysis(['fastplot.py' ], pathex=['D:\\install_test\\DAGUI-0.1\\bin' ], binaries=[], datas=[], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False , win_private_assemblies=False , cipher=block_cipher) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, exclude_binaries=True , name='fastplot' , debug=False , strip=False , upx=True , console=False ) coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False , upx=True , name='fastplot' )
spec文件中主要包含4个class: Analysis, PYZ, EXE和COLLECT.
Analysis以py文件为输入,它会分析py文件的依赖模块,并生成相应的信息
PYZ是一个.pyz的压缩包,包含程序运行需要的所有依赖
EXE根据上面两项生成
COLLECT生成其他部分的输出文件夹,COLLECT也可以没有
2. spec文件配置 首先给出举例python项目的spec文件配置
注意注意 :对于在源目录下的文件或目录可以只写文件名不写路径,子目录必须使用绝对路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import sysimport os.path as ospsys.setrecursionlimit(5000 ) block_cipher = None SETUP_DIR = 'D:\\install_test\\FASTPLOT\\' a = Analysis(['fastplot.py' , 'frozen_dir.py' , 'D:\\install_test\\FASTPLOT\\lib\\app\\start.py' , 'D:\\install_test\\FASTPLOT\\lib\\models\\analysis_model.py' , 'D:\\install_test\\FASTPLOT\\lib\\models\\datafile_model.py' , 'D:\\install_test\\FASTPLOT\\lib\\models\\data_model.py' , 'D:\\install_test\\FASTPLOT\\lib\\models\\figure_model.py' , 'D:\\install_test\\FASTPLOT\\lib\\models\\time_model.py' , 'D:\\install_test\\FASTPLOT\\lib\\models\\mathematics_model.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\constant.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\custom_dialog.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\data_dict_window.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\data_process_window.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\data_sift_window.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\mathematics_window.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\para_temp_window.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\mainwindow.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\paralist_window.py' , 'D:\\install_test\\FASTPLOT\\lib\\views\\plot_window.py' ], pathex=['D:\\install_test\\FASTPLOT' ], binaries=[], datas=[(SETUP_DIR+'lib\\icon' ,'lib\\icon' ),(SETUP_DIR+'data' ,'data' ),('policy_check_rule.xlsx' ,'.' ) ], hiddenimports=['pandas' ,'pandas._libs' ,'pandas._libs.tslibs.np_datetime' ,'pandas._libs.tslibs.timedeltas' , 'pandas._libs.tslibs.nattype' , 'pandas._libs.skiplist' ,'scipy._lib' ,'scipy._lib.messagestream' ], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False , win_private_assemblies=False , cipher=block_cipher) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, exclude_binaries=True , name='fastplot' , debug=False , strip=False , upx=True , console=True , icon='myicon.ico' ) coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False , upx=True , name='fastplot' )
a). py文件打包配置 针对多目录多文件的python项目,打包时候需要将所有相关的py文件输入到Analysis类里。Analysis类中的pathex定义了打包的主目录,对于在此目录下的py文件可以只写文件名不写路径,子目录中py文件必须使用绝对路径 。如上的spec脚本,将所有项目中的py文件路径以列表形式写入Analysis,这里为了说明混合使用了绝对路径和相对路径。
b). 资源文件打包配置 资源文件包括打包的python项目使用的相关文件,如图标文件,文本文件等。对于此类资源文件的打包需要设置Analysis的datas ,如例子所示datas接收元组:datas=[(SETUP_DIR+'lib\icon','lib\icon'),(SETUP_DIR+'data','data')]。元组的组成为(原项目中资源文件路径,打包后路径 ),例子中的(SETUP_DIR+'lib\icon','lib\icon')表示从D:\install_test\FASTPLOT\lib\icon下的图标文件打包后放入打包结果路径下的lib\icon目录。例子中('policy_check_rule.xlsx','.')表示从源码目录打包文件直接放入结果路径下。
c). ICON 图标配置 图标文件在EXE类中添加icon='myicon.ico' 属性进行设置。
d). Hidden import配置 pyinstaller在进行打包时,会解析打包的python文件,自动寻找py源文件的依赖模块。但是pyinstaller解析模块时可能会遗漏某些模块(not visible to the analysis phase),造成打包后执行程序时出现类似No Module named xxx。这时我们就需要在Analysis下hiddenimports中加入遗漏的模块,如例子中所示。
e). 递归深度设置 在打包导入某些模块时,常会出现"RecursionError: maximum recursion depth exceeded"的错误,这可能是打包时出现了大量的递归超出了python预设的递归深度。因此需要在spec文件上添加递归深度的设置,设置一个足够大的值来保证打包的进行,即
1 2 import syssys.setrecursionlimit(5000 )
f). 去除不必要的模块import 有时需要让pyinstaller不打包某些用不到的模块,可通过在excludes=[]中添加此模块实现,如
打包后执行程序提示找不到文件 注意 :该案例只适用打包成单个目录中多个文件,不适用于打包成单个exe文件。
打包完毕之后执行程序提示找不到文件:
1 2 3 4 5 6 7 Please input configuration file or file path and name: Traceback (most recent call last): File "main.py" , line 180, in <module> File "main.py" , line 118, in main File "main.py" , line 80, in neteye_cfg_file_read FileNotFoundError: [Errno 2] No such file or directory: '.\\cfg_file\\' [17792] Failed to execute script main
这十有八九和你Python程序书写有BUG相关,因为你再语句中使用了相对路径。但是当执行程序的时候所处的目录却并非程序文件所在路径,所以要使用os.chdir()方法变更当前工作目录 。
1 2 3 cwd = os.path.dirname(os.path.realpath(sys.argv[0 ])) os.chdir(cwd)
参考: pyinstaller使用方法 https://www.jb51.net/article/187806.htm
https://blog.csdn.net/wanzheng_96/article/details/108556950
https://stackoverrun.com/cn/q/9124269
pyinstaller文件路径获取 https://blog.csdn.net/qq_31801903/article/details/81666124
https://blog.csdn.net/Iv_zzy/article/details/107407167
https://www.jb51.net/article/184736.htm
https://www.jb51.net/article/52410.htm
https://www.jb51.net/article/163664.htm
一些其他的BUG记录 判断文件是否存在,但是直接回车提示错误。因为直接回车当前目录是存在的,但是只能读取文件所以报错。判断一下是否文件即可解决。
1 if (os.path.exists(file_name) and os.path.isfile(file_name)):