一般来说Python打包成系统可执行文件,有两个库,但支持更新版本(3.6+)的Python的就是Pyinstaller了,有趣的是Pyinstaller在windows7上运行的十分完美,到windows10上就有一些warning,它是由于win10的feature导致的,这个warning并不影响我们的打包。
在win10上面打包虽然有warning,但是打包出来的exe放到别的电脑上跑就没有问题。在win7打包出来的,放到别的win7上就找不到dll,我差点因为这个而挂科。
安装Pyinstaller
首先pip install pyinstaller
安装这个第三方库,先尝试使用一下,如果出现提示要安装pywin32之类的,就去 https://github.com/mhammond/pywin32/releases 找到适合自己Python和系统版本的Pywin32,然后下载安装。
- 注意:
如果你的Python安装路径里带有空格,需要修改对应目录下的某个文件的注释。但我这里不写出来,因为如果你还把Python装在带有空格的目录下,就算这个问题能够解决,以后还会有其他的问题。
趁早把安装路径改了吧。
打包
直接将命令行切换到写好的运行文件目录下,运行命令pyinstaller -F 文件名
会帮你处理好依赖关系和文件,打包成一个exe文件在目录下的dist文件夹里。你可以去掉-F
,这样子就会打包成一个文件夹的形式,同样会有一个入口exe文件在文件夹里。
如果你觉得默认图标太丑(反正我觉得太丑),可以在打包的时候加上-i 图标文件路径
来增加图标,图标应该像你所使用的其他任何软件一样 —— 最好使用.ico文件。
黑框这种东西,外行人看起来总是觉得很low,想要打包之后的exe运行没有黑框,只要在打包的时候加上-w
即可。
更多的选项可以查看 Pyinstaller的文档
打包多进程
当你尝试直接打包一个使用了multproecssing模块的多进程Python程序时,它肯定不会正常的按照你的意志进行打包。
pyinstaller的开发者对此专门写了一篇Wiki。当你使用最新版的Pyinstaller的时候,只需要如下,加一行代码即可。
if __name__ == "__main__":
multiprocessing.freeze_support()
当你的Pyinstaller版本低于3.3,就比较复杂了,你需要加上这个代码
import os
import sys
# Module multiprocessing is organized differently in Python 3.4+
try:
# Python 3.4+
if sys.platform.startswith('win'):
import multiprocessing.popen_spawn_win32 as forking
else:
import multiprocessing.popen_fork as forking
except ImportError:
import multiprocessing.forking as forking
if sys.platform.startswith('win'):
# First define a modified version of Popen.
class _Popen(forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
# We have to set original _MEIPASS2 value from sys._MEIPASS
# to get --onefile mode working.
os.putenv('_MEIPASS2', sys._MEIPASS)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
# On some platforms (e.g. AIX) 'os.unsetenv()' is not
# available. In those cases we cannot delete the variable
# but only set it to the empty string. The bootloader
# can handle this case.
if hasattr(os, 'unsetenv'):
os.unsetenv('_MEIPASS2')
else:
os.putenv('_MEIPASS2', '')
# Second override 'Popen' class with our modified version.
forking.Popen = _Popen
当然,现在pip安装的,都是3.3版本以上的。
打包额外文件
当需要打包的时候把一些其他文件复制到dist中。可以增加额外的命令参数:--add-data="文件路径;复制后的文件路径"
例如复制根目录下的snake.ico
文件到打包后的文件夹的根目录下--add-data="snake.ico;."
,在类Unix系统(MacOS,Linux)中使用:
替换;
。