自己写好的 python 程序在自己的 python 环境中运行没有问题. 但是如果要发布给别人使用, 那么对方也需要有 python 环境. 否则就需要将我们的 python 程序发布为一个可执行文件.
PyInstaller
PyInstaller 是一个十分有用的第三方库, 它能够在 Windows,Linux,Mac OS X 等操作系统下将 Python 源文件打包, 通过对源文件打包, Python 程序可以在没有安装 Python 的环境中运行, 也可以作为一个独立文件方便传递和管理.
PyInstaller 的官网: http://www.pyinstaller.org/
安装
使用 pip 命令就可以完成安装:
pip install pyinstaller
不过可能国外的源被墙了, 这里还可以指定第三方的源来安装:
pip install -i https://mirrors.163.com/pypi/simple pyinstaller
安装完成后, 会生成一个 pyinstaller.exe 的文件在你的 Scripts 文件夹里, 就是 pip.exe 的那个文件夹. 之后就用这个来打包我们的程序. 还有一个文件是 pyi-makespec.exe 也是的.
直接打包程序
使用下面的命令将程序打包:
pyinstaller <主程序名>.py
打完完成后会生成 build 和 dist 两个文件夹. 其中, build 目录是 pyinstaller 存储临时文件的目录, 可以安全删除. 最终的打包程序在 dist 内部的 <主程序名> 目录中. 另外还有一个 <主程序名>.spec 的文件, 下面会讲到, 也是可以删除的.
注意: 这样打包你的程序不能包含其他资源文件. 没有 import 的文件应该都不会打包进去的, 貌似程序本身也没有办法判断要包含哪些资源, 总不能一句一句去分析你的源码吧.
其实这里手动把你的资源文件 copy 过去也就 OK 了, 不过这个不是正规路子.
生成规范文件再打包
通过编辑一个规范文件, 告知程序需要包含哪些资源文件, 通过这个规范文件进行打包. 生成默认规范文件的命令:
pyi-makespec <主程序名>.py
其实, 之前直接打包的时候, 也是先生成默认的规范文件的, 然后在根据这个规范文件进行打包. 这里只是把这个过程分成了 2 步. 中间你可以修改这个规范文件, 然后再进入下一步的打包.
默认的文件内容如下:
- # -*- mode: python -*-
- block_cipher = None
- a = Analysis(['showlist.py'],
- pathex=['I:\\Python 自动化开发学习 \\ 作业 \\week1\\ 多级菜单'],
- 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='showlist',
- debug=False,
- strip=False,
- upx=True,
- console=True )
- coll = COLLECT(exe,
- a.binaries,
- a.zipfiles,
- a.datas,
- strip=False,
- upx=True,
- name='showlist')
修改 datas 这个变量, 把你的资源文件添加到后面的列表里去. 下面的例子中, 我先定义一个变量 added_files, 然后将这个列表赋值给 datas. 列表元素是元组, 前面是你的资源的路径(这里是相对路径了), 后面是要放到打包文件的哪个位置具体如下:
- # -*- mode: python -*-
- block_cipher = None
- added_files = [
- ('poetry', 'poetry'),
- ('list.txt', '.'),
- ]
- a = Analysis(['showlist.py'],
- pathex=['I:\\Python 自动化开发学习 \\ 作业 \\week1\\ 多级菜单'],
- binaries=[],
- datas=added_files,
- 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='showlist',
- debug=False,
- strip=False,
- upx=True,
- console=True )
- coll = COLLECT(exe,
- a.binaries,
- a.zipfiles,
- a.datas,
- strip=False,
- upx=True,
- name='showlist')
通过规范文件打包, 规范文件修改后之后, 使用下面的命令指定规范文件进行打包:
pyinstaller <规范文件名>.spec
执行完成后, 现在打包好的程序里就包含了我们添加的资源文件了. 其实效果和我们自己时候手动复制是一样的.
会修改规范文件, 就不需要用到下面的参数了.
有用的参数
使用 - h 可以看到参数的说明, 下面是几个比较有用的参数.
另外使用参数就不需要用使用规范文件了. 使用了参数的本质还是先生成一个规范文件, 这个规范文件会根据我们的参数有一些变化, 然后还是通过规范文件进行打包. 可以通过使用参数打包后查看自动生成的规范文件进行比较来验证.
生成单个文件(-F, --onefile)
命令:
pyinstaller -F <主程序名>.py
或
pyinstaller <主程序名>.py -F
这里我是试出来直接打包不包含资源文件的程序. 成功后 dist 文件夹下面就只会有一个可执行文件, 而且大小也比之前的文件夹小了很多. 不过网上说启动程序会变慢, 自己把握把.
如果是包含资源文件的规范文件使用 - F 参数打包, 最后得到的还是一个目录.
指定资源文件(--add-data [SRC;DEST or SRC:DEST] )
前面是源, 后面对目的, 中间是分隔符. windows 系统使用分号(;),Linux 系统使用冒号(:). 并且这个参数可以多次使用. 下面就是添加了 2 个资源文件:
pyinstaller showlist.py --add-data poetry;poetry --add-data list.txt;.
最后的效果还是和上面使用规范文件再打包一样, 感觉还是用规范文件的方式好一点. 这里可以比较一下系统自动生成的规范文件.
这里尝试结合 - F 一起使用, 但是生成的单文件里测试下来还是没有包含资源文件. 大概就是不能连资源文件一起打包成单一文件的. 不过把资源文件复制过去还是可以用的. 也就是你的主程序还是单文件的, 但是资源文件独立在外面.
指定图标(-i [FILE.ico or FILE.exe,ID or FILE.icns] , --icon [FILE.ico or FILE.exe,ID or FILE.icns] )
指定个图标还是蛮有用的, 不过试下来, 单文件还是貌似无效. 只有用文件夹, 然后里面主程序的图标会变成你指定的图标.
pyinstaller <主程序名>.py -i <图标>.ico
同样的, 规范文件里也是有地方指定图标的:
- exe = EXE(pyz,
- a.scripts,
- exclude_binaries=True,
- name='showlist',
- debug=False,
- strip=False,
- upx=True,
- console=True , icon='name.ico')
小结
推荐先生成规范文件, 然后编辑一下, 在通过规范文件来打包
还是不要生成单文件了, 我试下来也比较鸡肋
自己用或者和别人交流也不用打包了, 几十 k 的代码包下来十几兆. 因为考虑到没有 python 环境, 应该是把要用到的库也都包进去了
最后打包发布给外行用用还是不错的, 在搞个图标包装一下, nice.
展开 - wx 模块
有一个 wx 模块, 是用来做界面的.
做出窗口界面, 包装好我们的 python 程序, 最后再打包成可执行文件来发布. 这样一个 python 软件就出来了.
来源: http://www.bubuko.com/infodetail-2588531.html