用pyinstaller打包python程序

1.概述

需求:当我们用python写好一个单机版小程序,想发布在网上或给朋友使用时,我们希望能将程序和python环境一起打包成一个可执行文件双击运行即可,网友下载后直接运行不需要再安装python环境和相关依赖。
pyinstaller是一个能将Python程序转换成单个可执行文件的程序, 操作系统支持Windows, Linux, Mac OS X, Solaris和AIX。并且很多包都支持开箱即用,不依赖环境。

2.打包

此处我们以win10+python3.5+virtualenv环境为例演示打包过程
先准备一个写好的python小程序,我们用Flask结巴分词的cut分词展示在网页上源码下载

在一个空目录中创建一个virtualenv的虚拟环境,并安装应用的相关依赖:

D:\workspace\Python\test\test-pyinstaller>virtualenv env
Using base prefix 'c:\\soft\\python\\python3'
New python executable in D:\workspace\Python\test\test-pyinstaller\env\Scripts\python.exe
Installing setuptools, pip, wheel...done.

D:\workspace\Python\test\test-pyinstaller>env\Scripts\activate

(env) D:\workspace\Python\test\test-pyinstaller>pip install Flask
Collecting Flask
  Using cached Flask-0.12.2-py2.py3-none-any.whl
Collecting itsdangerous>=0.21 (from Flask)
Collecting Werkzeug>=0.7 (from Flask)
  Using cached Werkzeug-0.12.2-py2.py3-none-any.whl
Collecting click>=2.0 (from Flask)
  Using cached click-6.7-py2.py3-none-any.whl
Collecting Jinja2>=2.4 (from Flask)
  Using cached Jinja2-2.9.6-py2.py3-none-any.whl
Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->Flask)
Installing collected packages: itsdangerous, Werkzeug, click, MarkupSafe, Jinja2, Flask
Successfully installed Flask-0.12.2 Jinja2-2.9.6 MarkupSafe-1.0 Werkzeug-0.12.2 click-6.7 itsdangerous-0.24

(env) D:\workspace\Python\test\test-pyinstaller>pip install jieba
Collecting jieba
Installing collected packages: jieba
Successfully installed jieba-0.38

(env) D:\workspace\Python\test\test-pyinstaller>

在虚拟环境中安装打包需要的依赖:
在windows环境中会依赖win32api,所以需要下载pywin32,在此处下载对应python版本的pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/,下载好后用easy_install安装;安装完成后再安装pyinstaller,此处从git上安装最新版本的pyinstaller

(env) D:\workspace\Python\test\test-pyinstaller>easy_install pywin32-221.win-amd64-py3.5.exe
(env) D:\workspace\Python\test\test-pyinstaller>pip install git+https://github.com/pyinstaller/pyinstaller

环境准备完毕,我们项目中的目录结构如下:

image.png

pyinstaller打包命令如下:

pyinstaller [-F] [-w] [-p 模块] [-i logo.icon] 程序入口文件路径
参数说明:
-F 表示生成单个可执行文件
-w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!
-p 表示你自己自定义需要加载的类路径,一般情况下用不到
-i 表示可执行文件的图标

在程序目录执行如下命令进行打包:

(env) D:\workspace\Python\test\test-pyinstaller>pyinstaller app.py

打包完成后目录结构如下:

image.png

在dist目录中会包含一个与可执行文件同名的目录,目录里面会有一个与可执行文件同名的.exe文件,这个文件及为可执行文件。

image.png

若我们的程序依赖一些静态资源我们需要将静态资源拷贝到可执行文件所在目录,我们上面的程序需要将模板文件与结巴分词的词典拷贝进去。

image.png

然后双击app.exe启动flask应用,在网页访问查看效果:

image.png

3.踩过的坑

安装pyinstaller时直接使用pip install pyinstaller,打包时会报一些错误,所以直接安装git上的最新版

如我们程序中使用了多进程multiprocessing,我们需要创建一个模块内容如下:

# 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

然后在我们的main方法的最前面调用如下代码:

import multiprocessing
    multiprocessing.freeze_support()

4.参考

使用PyInstaller打包Python程序
pyinstaller的库导入和多进程打包问题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容