打包可执行包_Python学习笔记:打包和发布

打包和发布

两个常用的发布工具:zipapp和PyInstaller
zipapp模块可用于生成可执行的Python档案包,这个档案包会包含目录下所有的Python程序。如果使用pip工具先将Python程序所依赖的模块下载到目标目录下,那么就可以生成可独立运行的Python程序一一只要目标机器上安装有Python解释器环境即可。
PyIntaller工具则更强大,它可以直接将Python程序编译成Windows、MacOSX平台上的可执行程序,这种可执行程序可直接被分发到其他Windows、MacOSX计算机上,而无须在这些机器上安装Python环境。

使用zipapp模块

Python提供了一个zipapp模块,通过该模块可以将一个Python模块(可能包含很多个源程序)打包成一个Python应用,甚至发布成一个Windows的可执行程序。

生成可执行的Python档案包

zipapp是一个可以直接运行的模块,该模块用于将单个Python文件或整个目录下的所有文件打包成可执行的档案包。该模块的命令行语法如下:

1python -m zipapp source [options]

在上面命令中,source参数代表要打包的Python源程序或目录,该参数既可以是单个的Python文件,也可以是文件夹。如果source参数是文件夹,那么zipapp模块会打包该文件夹中的所有Python文件。
该命令的options支持如下选项:

0c01ac788dbc085c8ffb9303574088dd.png

建立一个app子目录,该子目录用于包含多个Python程序。首先在该目录下开发一个say_hello.py程序:
1def say_hello(name):
2    return name + ",您好!"

然后在该目录下开发一个app.py程序来使用say_hello模块。

1from say_hello import *
2
3def main():
4    print('程序开始执行')
5    print(say_hello('孙悟空'))

然后输入命令:

1python -m zipapp app -o first.pyz -m "app:main"

上面命令指定将当前目录下的app子目录下的所有Python源文件打包成一个档案包,并通过-0选项指定所生成的档案包的文件名为first.pyz;-m选项指定使用app.py模块中的main函数作为程序入口。
运行上面命令,将会生成一个first.pyz文件。接下来可以使用python命令来运行first.pyz文件

1C:\Users\zz\PycharmProjects\pythonProject>python -m zipapp app -o first.pyz -m "app:main"
2
3C:\Users\zz\PycharmProjects\pythonProject>python first.pyz
4程序开始执行
5孙悟空,您好!

没有指定-o选项,这意味着该命令将会使用默认的输出文件名:source参数值加.pyz后缀。运行上面命令,将会在当前目录下生成一个app.pyz文件。

1C:\Users\zz\PycharmProjects\pythonProject>python -m zipapp app -m "app:main"
2
3C:\Users\zz\PycharmProjects\pythonProject>python app.pyz
4程序开始执行
5孙悟空,您好!

创建独立应用

通过上面介绍的方式打包得到的档案包中只有当前项目的Python文件,如果Python应用还需要使用第三方模块和包,那么仅打包该应用的Python程序是不够的。
为了创建能独立启动的应用(自带依赖模块和包),需要执行两步操作。

  • 将应用依赖的模块和包下载到应用目录中。

  • 使用zipapp将应用和依赖模块一起打包成档案包。

创建一个子目录,再该子目录创建一个 test.py 文件,test.py内容如下:

1# 导入访问wx的模块
2import wx
3
4def hello():
5    print("Hello----!!!")

接下来继续新建一个 mian__.py文件作为程序入口,这样程序在打包档案包时就不需要指定程序入口了。__mian.py 内容如下:

1# 导入当前目录下的 test 模块
2from test import *
3
4hello()

dbapp目录当前文件:

9a39235f39942da2a38e8fdab665d53c.png

然后在当前目录新建一个 requirements.txt 文件,文件内容:wxPython
最后按照如下步骤将dbapp子目录下的应用打包成独立应用。
  1. 通过命令行工具执行如下命令

1python -m pip install -r requirements.txt --target dbapp

上面命令实际上就是使用pip模块来安装模块,其中python -m pip install表示要安装模块。--target选项指定将模块安装到指定目录下,此处指定将依赖模块安装到dbapp子目录下。-r选项指定要安装哪些模块,此处使用requirements.txt文件列出要安装的模块和包。-r选项支持两个值:

  • 直接指定要安装的模块或包。

  • 使用清单文件指定要安装的模块和包。

当应用依赖的模块较多时,建议使用清单文件来列出所依赖的模块。在 requirements.txt 文件中定义多行,每行定义一个模块。
运行上面命令将看到pip开始下载 wxPython模块,下载完成后将可以在 dbapp子目录下看到大量 有关 wxPython 模块的文件。

 1C:\Users\zz\PycharmProjects\pythonProject>python -m pip install -r requirements.txt --target dbapp
2Collecting wxPython
3  Downloading wxPython-4.1.1-cp37-cp37m-win_amd64.whl (18.2 MB)
4     |████████████████████████████████| 18.2 MB 400 kB/s
5Collecting numpy; python_version >= "3.0"
6  Downloading numpy-1.19.5-cp37-cp37m-win_amd64.whl (13.2 MB)
7     |████████████████████████████████| 13.2 MB 1.7 MB/s
8Collecting pillow
9  Downloading Pillow-8.1.0-cp37-cp37m-win_amd64.whl (2.2 MB)
10     |████████████████████████████████| 2.2 MB 2.2 MB/s
11Collecting six
12  Downloading six-1.15.0-py2.py3-none-any.whl (10 kB)
13Installing collected packages: numpy, pillow, six, wxPython
14Successfully installed numpy-1.19.5 pillow-8.1.0 six-1.15.0 wxPython-4.1.1
79b98a28a5e55156d339f614ba025044.png
  1. 如果pip在dbapp子目录下生成了.dist-info目录,则建议删除该目录。

  2. 使用zipapp模块执行打包操作。由于本例的dbapp子目录下包含了mian.py文件,该文件将会作为程序入口,因此打包时不需要指定-m选项。使用如下命令来打包。

1python -m zipapp dbapp

与上一节所使用的命令相比,该命令没有使用-m选项来指定程序入口,该程序将会使用档案包中的mian.py文件作为程序入口。
运行上面命令,将会得到一个大约 121MB的档案包,该档案包自动包含了 wxPython模块,所以比较大。
在创建了独立应用之后,只要目标机器上安装了合适版本的Python解释器,即可运行该独立应用。

使用PyInstaller生成可执行程序

在创建了独立应用(自包含该应用的依赖包)之后,还可以使用PyInstaller将Python程序生成可直接运行的程序,这个程序就可以被分发到对应的Windows或MacOSX平台上运行。

安装PyInstaller

Python默认并不包含PyInstaller模块,因此需要自行安装PyInstaller模块。安装Pylnstal!er模块与安装其他Python模块一样,使用pip命令安装即可。

1pip install pyinstaller
c67dcbc79a5c3c1edbec12e9dbab1a67.png

安装过程:
 1C:\Users\zz\PycharmProjects\pythonProject>pip install pyinstaller
2Collecting pyinstaller
3  Downloading pyinstaller-4.1.tar.gz (3.5 MB)
4     |████████████████████████████████| 3.5 MB 82 kB/s
5  Installing build dependencies ... done
6  Getting requirements to build wheel ... done
7    Preparing wheel metadata ... done
8Collecting altgraph
9  Downloading altgraph-0.17-py2.py3-none-any.whl (21 kB)
10Collecting pywin32-ctypes>=0.2.0; sys_platform == "win32"
11  Downloading pywin32_ctypes-0.2.0-py2.py3-none-any.whl (28 kB)
12Requirement already satisfied: setuptools in d:\6.commontools\python379\lib\site-packages (from pyinstaller) (47.1.0)
13Collecting pyinstaller-hooks-contrib>=2020.6
14  Downloading pyinstaller_hooks_contrib-2020.11-py2.py3-none-any.whl (172 kB)
15     |████████████████████████████████| 172 kB 23 kB/s
16Collecting pefile>=2017.8.1; sys_platform == "win32"
17  Downloading pefile-2019.4.18.tar.gz (62 kB)
18     |████████████████████████████████| 62 kB 58 kB/s
19Collecting future
20  Downloading future-0.18.2.tar.gz (829 kB)
21     |████████████████████████████████| 829 kB 51 kB/s
22Using legacy setup.py install for pefile, since package 'wheel' is not installed.
23Using legacy setup.py install for future, since package 'wheel' is not installed.
24Building wheels for collected packages: pyinstaller
25  Building wheel for pyinstaller (PEP 517) ... done
26  Created wheel for pyinstaller: filename=pyinstaller-4.1-py3-none-any.whl size=2790249 sha256=821086b72ae6fce2c8497e95202d67102f3bf6e0b31fd91b0091d63bfba34260
27  Stored in directory: c:\users\zz\appdata\local\pip\cache\wheels\88\45\3d\170873c056ce9fad2bcb546a1647db6c6111fa7016335b30f0
28Successfully built pyinstaller
29Installing collected packages: altgraph, pywin32-ctypes, pyinstaller-hooks-contrib, future, pefile, pyinstaller
30    Running setup.py install for future ... done
31    Running setup.py install for pefile ... done
32Successfully installed altgraph-0.17 future-0.18.2 pefile-2019.4.18 pyinstaller-4.1 pyinstaller-hooks-contrib-2020.11 pywin32-ctypes-0.2.0

在PyInstaller模块安装成功之后,在Python的安装目录下的Scripts(D:\6.CommonTools\python379\Scripts)目录下会增加一个pyinstaller.exe程序,接下来就可以使用该工具将Python程序生成EXE程序了。

生成可执行程序

PyInstaller工具的命令语法如下:

1pyinstaller 选项 Python源文件

不管这个Python应用是单文件的应用,还是多文件的应用,只要在使用pyinstaller命令时编译作为程序入口的Python程序即可。

0ca69bb525415a45c2556f2410dd44a1.png

将app子目录下的 app.py 文件略作修改,修改成可执行的Python程序。
1from say_hello import *
2
3def main():
4    print('程序开始执行')
5    print(say_hello('孙悟空'))
6
7# 增加调用main()函数
8if __name__ == '__main__':
9    main()

接下来使用命令行工具进入 app 子目录,执行如下命令:

1pyinstaller -F app.py

执行上面命令,将看到详细的生成过程。当生成完成后,将会在 app 子目录下看到多了一个dist目录,并在该目录下看到有一个app.exe文件,这就是使用PyInstaller工具生成的EXE程序。

 1C:\Users\zz\PycharmProjects\pythonProject\app>pyinstaller -F app.py
2181 INFO: PyInstaller: 4.1
3181 INFO: Python: 3.7.9
4182 INFO: Platform: Windows-10-10.0.18362-SP0
5184 INFO: wrote C:\Users\zz\PycharmProjects\pythonProject\app\app.spec
6196 INFO: UPX is not available.
7199 INFO: Extending PYTHONPATH with paths
8['C:\\Users\\zz\\PycharmProjects\\pythonProject\\app',
9 'C:\\Users\\zz\\PycharmProjects\\pythonProject\\app']
10213 INFO: checking Analysis
11213 INFO: Building Analysis because Analysis-00.toc is non existent
12214 INFO: Initializing module dependency graph...
13218 INFO: Caching module graph hooks...
14240 INFO: Analyzing base_library.zip ...
153189 INFO: Processing pre-find module path hook distutils from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path\\hook-dis16tutils.py'.
173193 INFO: distutils: retargeting to non-venv dir 'd:\\6.commontools\\python379\\lib'
184226 INFO: Caching module dependency graph...
194369 INFO: running Analysis Analysis-00.toc
204384 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
21  required by d:\6.commontools\python379\python.exe
224521 INFO: Analyzing C:\Users\zz\PycharmProjects\pythonProject\app\app.py
234525 INFO: Processing module hooks...
244525 INFO: Loading module hook 'hook-difflib.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
254528 INFO: Excluding import of doctest from module difflib
264528 INFO: Loading module hook 'hook-distutils.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
274530 INFO: Loading module hook 'hook-encodings.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
284932 INFO: Loading module hook 'hook-heapq.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
294934 INFO: Excluding import of doctest from module heapq
304934 INFO: Loading module hook 'hook-pickle.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
314936 INFO: Excluding import of argparse from module pickle
324936 INFO: Loading module hook 'hook-sysconfig.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
334937 INFO: Loading module hook 'hook-xml.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
345184 INFO: Looking for ctypes DLLs
355184 INFO: Analyzing run-time hooks ...
365189 INFO: Looking for dynamic libraries
375503 INFO: Looking for eggs
385504 INFO: Using Python library d:\6.commontools\python379\python37.dll
395504 INFO: Found binding redirects:
40[]
415507 INFO: Warnings written to C:\Users\zz\PycharmProjects\pythonProject\app\build\app\warn-app.txt
425564 INFO: Graph cross-reference written to C:\Users\zz\PycharmProjects\pythonProject\app\build\app\xref-app.html
435684 INFO: checking PYZ
445689 INFO: Building PYZ because PYZ-00.toc is non existent
455691 INFO: Building PYZ (ZlibArchive) C:\Users\zz\PycharmProjects\pythonProject\app\build\app\PYZ-00.pyz
466238 INFO: Building PYZ (ZlibArchive) C:\Users\zz\PycharmProjects\pythonProject\app\build\app\PYZ-00.pyz completed successfully.
476248 INFO: checking PKG
486250 INFO: Building PKG because PKG-00.toc is non existent
496251 INFO: Building PKG (CArchive) PKG-00.pkg
508346 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
518352 INFO: Bootloader d:\6.commontools\python379\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
528353 INFO: checking EXE
538353 INFO: Building EXE because EXE-00.toc is non existent
548355 INFO: Building EXE from EXE-00.toc
558357 INFO: Appending archive to EXE C:\Users\zz\PycharmProjects\pythonProject\app\dist\app.exe
568369 INFO: Building EXE from EXE-00.toc completed successfully.

生成后的目录结构:

 1C:\Users\zz\PycharmProjects\pythonProject\app>tree /f
2│  app.py
3│  app.spec
4│  say_hello.py
5│
6├─build
7│  └─app
8│          Analysis-00.toc
9│          app.exe.manifest
10│          base_library.zip
11│          EXE-00.toc
12│          PKG-00.pkg
13│          PKG-00.toc
14│          PYZ-00.pyz
15│          PYZ-00.toc
16│          warn-app.txt
17│          xref-app.html
18│
19├─dist
20│      app.exe
21│
22└─__pycache__
23        app.cpython-37.pyc

在命令行窗口中进入 app\dist\ 目录下,在该目录下执行app.exe,将会看到该程序生成如下输出结果。

1C:\Users\zz\PycharmProjects\pythonProject\app\dist>app.exe
2程序开始执行
3孙悟空,您好!
04b898d6af2b8d89dbef4f96007a71b7.png

在上面命令中使用了-F选项,该选项指定生成单独的EXE文件,因此,在dist目录下生成了一个单独的大约为6MB的app.exe文件(在MacOSX平台上生成的文件就叫app,没有后缀);与-F选项对应的是-D选项(默认选项),该选项指定生成一个目录(包含多个文件)来作为程序。
下面先将PyInstaller工具在app目录下生成的build,dist目录删除,并将app.spec文件也删除,然后使用如下命令来生成EXE文件。
1pyinstaller -D app.py

生成过程:

 1C:\Users\zz\PycharmProjects\pythonProject\app>pyinstaller -D app.py
2135 INFO: PyInstaller: 4.1
3135 INFO: Python: 3.7.9
4138 INFO: Platform: Windows-10-10.0.18362-SP0
5143 INFO: wrote C:\Users\zz\PycharmProjects\pythonProject\app\app.spec
6153 INFO: UPX is not available.
7158 INFO: Extending PYTHONPATH with paths
8['C:\\Users\\zz\\PycharmProjects\\pythonProject\\app',
9 'C:\\Users\\zz\\PycharmProjects\\pythonProject\\app']
10183 INFO: checking Analysis
11183 INFO: Building Analysis because Analysis-00.toc is non existent
12184 INFO: Initializing module dependency graph...
13191 INFO: Caching module graph hooks...
14219 INFO: Analyzing base_library.zip ...
152982 INFO: Processing pre-find module path hook distutils from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path\\hook-dis16tutils.py'.
172983 INFO: distutils: retargeting to non-venv dir 'd:\\6.commontools\\python379\\lib'
184377 INFO: Caching module dependency graph...
194513 INFO: running Analysis Analysis-00.toc
204516 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
21  required by d:\6.commontools\python379\python.exe
224666 INFO: Analyzing C:\Users\zz\PycharmProjects\pythonProject\app\app.py
234668 INFO: Processing module hooks...
244669 INFO: Loading module hook 'hook-difflib.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
254670 INFO: Excluding import of doctest from module difflib
264670 INFO: Loading module hook 'hook-distutils.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
274672 INFO: Loading module hook 'hook-encodings.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
285135 INFO: Loading module hook 'hook-heapq.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
295136 INFO: Excluding import of doctest from module heapq
305137 INFO: Loading module hook 'hook-pickle.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
315138 INFO: Excluding import of argparse from module pickle
325138 INFO: Loading module hook 'hook-sysconfig.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
335140 INFO: Loading module hook 'hook-xml.py' from 'd:\\6.commontools\\python379\\lib\\site-packages\\PyInstaller\\hooks'...
345393 INFO: Looking for ctypes DLLs
355393 INFO: Analyzing run-time hooks ...
365399 INFO: Looking for dynamic libraries
375644 INFO: Looking for eggs
385644 INFO: Using Python library d:\6.commontools\python379\python37.dll
395644 INFO: Found binding redirects:
40[]
415649 INFO: Warnings written to C:\Users\zz\PycharmProjects\pythonProject\app\build\app\warn-app.txt
425683 INFO: Graph cross-reference written to C:\Users\zz\PycharmProjects\pythonProject\app\build\app\xref-app.html
435690 INFO: checking PYZ
445691 INFO: Building PYZ because PYZ-00.toc is non existent
455691 INFO: Building PYZ (ZlibArchive) C:\Users\zz\PycharmProjects\pythonProject\app\build\app\PYZ-00.pyz
466192 INFO: Building PYZ (ZlibArchive) C:\Users\zz\PycharmProjects\pythonProject\app\build\app\PYZ-00.pyz completed successfully.
476201 INFO: checking PKG
486202 INFO: Building PKG because PKG-00.toc is non existent
496202 INFO: Building PKG (CArchive) PKG-00.pkg
506222 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
516225 INFO: Bootloader d:\6.commontools\python379\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
526226 INFO: checking EXE
536226 INFO: Building EXE because EXE-00.toc is non existent
546226 INFO: Building EXE from EXE-00.toc
556227 INFO: Appending archive to EXE C:\Users\zz\PycharmProjects\pythonProject\app\build\app\app.exe
566232 INFO: Building EXE from EXE-00.toc completed successfully.
576238 INFO: checking COLLECT
586238 INFO: Building COLLECT because COLLECT-00.toc is non existent
596242 INFO: Building COLLECT COLLECT-00.toc
606375 INFO: Building COLLECT COLLECT-00.toc completed successfully.

执行上面命令,将看到详细的生成过程。当生成完成后,将会在 app 目录下看到多了一个dist目录,并在该目录下看到有一个app子目录,内容如下:

fb4df9388d8677cdbd526c817185c788.png

在该子目录下包含了大量.dll文件和.pyd文件,它们都是app.exe程序的支撑文件。在命令行窗口中运行该app.exe程序,同样可以看到与前一个app.exe程序相同的输出结果。
20c6f808c1ff27767b948b153636791b.png

本章小结

本章主要介绍了两种打包Python程序的工具:zipapp和PyInstaller。zipapp主要用于将Python应用打包成一个.pyz文件。不管开发Python应用时有多少个源文件或多少个依赖包,使用zipapp都可以将它们打包成一个.pyz文件,该文件依然需要Python环境来执行。PyInstaller则直接将Python程序打包成可执行程序,而且该工具还是跨平台的,因此使用非常方便。使用PyInstaller打包出来的程序,完全可以被分发到对应平台的目标机器上直接运行,无须在目标机器上安装Python解释器环境。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值