用pyinstaller把python脚本打包成二进制文件
# 前言
在编写 python 脚本的时候,有时候我们会需要很多依赖库,如果只是脚本,在别的机器上运行就也需要安装这些依赖库,这是一个非常麻烦的时候,解决这个问题的思路有以下几种:
(1)、用 docker,在 docker 里解决这些依赖,然后封装成镜像,这样就可以在各种机器上运行了;
(2)、使用 virtualenv 进行本地包安装,然后把安装好的文件拷贝到服务器上;
(3)、把包打成二进制文件;
由于我们内部业务没用 docker,所以第一点就排除了,至于第二点还是比较麻烦,直接舍弃。妥妥的研究第三种了。
在用 pyinstaller 的时候踩了几个坑:
(1)、你原始主机(准备用来打包)的主机,如果环境比较混乱,比如有 pyhton2 也有 python3,在用 pyinstaller 的时候会出现一些莫名奇妙的错误(就是打出来的包用不了),我在这个坑里躺了很久;
(2)、如果你在 centos7 上打的包,跑到 centos6 上运行脚本,会报一些 openssl、glibc 等版本太低的问题,这种情况下,你在 centos7 上打的包就只能在 centos7 上跑,要在 6 上跑,只能用 centos6 的服务器打包;
# 一、安装
# 1、安装 pip(可选)
看你服务器上是否有 pip,如果没有,需要安装,安装方法如下:
# 通过yum来安装
yum install -y epel-release
yum install -y python-pip
# 通过安装脚本来安装(如果centos6的系统可能不适合)
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
2
3
4
5
6
7
# 2、安装 pyinstaller
# 在7的系统上可以直接执行下面语句,经过测试最新3.4的版本还有一些不知名的问题
# 当然不是所有的机器都能装上3.3版本,如果在安装的时候报ImportError....,就把版本降低试试
pip install pyinstaller==3.3
# 在6的系统上需要选择pyinstaller其他的版本,我在centos6.10上安装的是2.1的版本
pip install pyinstaller==2.1
2
3
4
5
6
# 二、原理
简单的说一下 pyinstaller 的原理:
PyInstaller 输入你指定的的脚本,首先分析脚本所依赖的其他脚本,然后去查找,复制,把所有相关的脚本收集起来,包括 Python 解析器,然后把这些文件放在一个目录下,或者打包进一个可执行文件里面。
可以直接发布输出的整个文件夹里面的文件,或者生成的可执行文件。你只需要告诉用户,你的应用 App 是自我包含的,不需要安装其他包,或某个版本的 Python,就可以直接运行了。
**需要注意的是:**PyInstaller 打包的执行文件,只能在和打包机器系统同样的环境下。也就是说,不具备可移植性,若需要在不同系统上运行,就必须针对该平台进行打包。
# 三、使用
语法:
pyinstaller [options] script [script ...] | specfile
参数介绍:
参数 | 含义 |
---|---|
-F | 指定打包后只生成一个可执行的文件 |
-D | –onedir 创建一个目录,包含可执行,但会依赖很多文件(默认选项) |
-c | –console, –nowindowed 使用控制台,无界面(默认) |
-w | –windowed, –noconsole 使用窗口,无控制台 |
-p | 添加搜索路径,让其找到对应的库。 |
-i | 改变生成程序的 icon 图标 |
由于我只是一些脚本,所以基本都只用"-F"参数。
测试:
(1)、不带参数脚本
[root@ecs-5704-0006 test]# cat test.py
print("hello world")
2
测试一下脚本是否有问题:
[root@ecs-5704-0006 test]# python test.py
hello world
2
用 pyinstaller 打包:
[root@ecs-5704-0006 test]# pyinstaller -F test.py
33 INFO: PyInstaller: 3.3
33 INFO: Python: 2.7.5
34 INFO: Platform: Linux-3.10.0-862.14.4.el7.x86_64-x86_64-with-centos-7.5.1804-Core
34 INFO: wrote /usr/local/src/test/test.spec
38 INFO: UPX is not available.
38 INFO: Extending PYTHONPATH with paths
['/usr/local/src/test', '/usr/local/src/test']
38 INFO: checking Analysis
38 INFO: Building Analysis because out00-Analysis.toc is non existent
38 INFO: Initializing module dependency graph...
40 INFO: Initializing module graph hooks...
91 INFO: running Analysis out00-Analysis.toc
103 INFO: Caching module hooks...
106 INFO: Analyzing /usr/local/src/test/test.py
106 INFO: Loading module hooks...
106 INFO: Loading module hook "hook-encodings.py"...
1764 INFO: Looking for ctypes DLLs
1764 INFO: Analyzing run-time hooks ...
1768 INFO: Looking for dynamic libraries
2032 INFO: Looking for eggs
2032 INFO: Using Python library /lib64/libpython2.7.so.1.0
2034 INFO: Warnings written to /usr/local/src/test/build/test/warntest.txt
2044 INFO: Graph cross-reference written to /usr/local/src/test/build/test/xref-test.html
2079 INFO: checking PYZ
2079 INFO: Building PYZ because out00-PYZ.toc is non existent
2079 INFO: Building PYZ (ZlibArchive) /usr/local/src/test/build/test/out00-PYZ.pyz
2245 INFO: Building PYZ (ZlibArchive) /usr/local/src/test/build/test/out00-PYZ.pyz completed successfully.
2273 INFO: checking PKG
2273 INFO: Building PKG because out00-PKG.toc is non existent
2273 INFO: Building PKG (CArchive) out00-PKG.pkg
4820 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
4829 INFO: Bootloader /usr/lib/python2.7/site-packages/PyInstaller/bootloader/Linux-64bit/run
4829 INFO: checking EXE
4829 INFO: Building EXE because out00-EXE.toc is non existent
4829 INFO: Building EXE from out00-EXE.toc
4829 INFO: Appending archive to ELF section in EXE /usr/local/src/test/dist/test
4841 INFO: Building EXE from out00-EXE.toc completed successfully.
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
然后会在脚本目录下生成 build 和 dist 目录,还有 test.spec 文件,我们需要的脚本就在 dist 目录下:
[root@ecs-5704-0006 test]# cd dist/
[root@ecs-5704-0006 dist]# ll
total 15048
-rwxr-xr-x 1 root root 4865824 Jun 19 17:21 test <---这就是我们需要的二进制文件
[root@ecs-5704-0006 dist]# ./test
hello world
2
3
4
5
6
(2)、带参数的脚本
[root@ecs-5704-0006 test]# cat test2.py
import sys
print("hello {}".format(sys.argv[1]))
[root@ecs-5704-0006 test]# python test2.py 12345
hello 12345
2
3
4
5
用 pyinstaller 打包:
[root@ecs-5704-0006 test]# pyinstaller -F test2.py
33 INFO: PyInstaller: 3.3
33 INFO: Python: 2.7.5
34 INFO: Platform: Linux-3.10.0-862.14.4.el7.x86_64-x86_64-with-centos-7.5.1804-Core
34 INFO: wrote /usr/local/src/test/test2.spec
37 INFO: UPX is not available.
38 INFO: Extending PYTHONPATH with paths
['/usr/local/src/test', '/usr/local/src/test']
38 INFO: checking Analysis
38 INFO: Building Analysis because out00-Analysis.toc is non existent
38 INFO: Initializing module dependency graph...
40 INFO: Initializing module graph hooks...
91 INFO: running Analysis out00-Analysis.toc
103 INFO: Caching module hooks...
106 INFO: Analyzing /usr/local/src/test/test2.py
106 INFO: Loading module hooks...
107 INFO: Loading module hook "hook-encodings.py"...
1777 INFO: Looking for ctypes DLLs
1777 INFO: Analyzing run-time hooks ...
1781 INFO: Looking for dynamic libraries
2047 INFO: Looking for eggs
2047 INFO: Using Python library /lib64/libpython2.7.so.1.0
2048 INFO: Warnings written to /usr/local/src/test/build/test2/warntest2.txt
2059 INFO: Graph cross-reference written to /usr/local/src/test/build/test2/xref-test2.html
2094 INFO: checking PYZ
2094 INFO: Building PYZ because out00-PYZ.toc is non existent
2094 INFO: Building PYZ (ZlibArchive) /usr/local/src/test/build/test2/out00-PYZ.pyz
2260 INFO: Building PYZ (ZlibArchive) /usr/local/src/test/build/test2/out00-PYZ.pyz completed successfully.
2288 INFO: checking PKG
2288 INFO: Building PKG because out00-PKG.toc is non existent
2288 INFO: Building PKG (CArchive) out00-PKG.pkg
4835 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
4843 INFO: Bootloader /usr/lib/python2.7/site-packages/PyInstaller/bootloader/Linux-64bit/run
4843 INFO: checking EXE
4843 INFO: Building EXE because out00-EXE.toc is non existent
4843 INFO: Building EXE from out00-EXE.toc
4843 INFO: Appending archive to ELF section in EXE /usr/local/src/test/dist/test2
4856 INFO: Building EXE from out00-EXE.toc completed successfully.
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
执行生成的二进制文件:
[root@ecs-5704-0006 dist]# ./test2 9999999
hello 9999999
2
作者:
本文链接:https://jokerbai.com
版权声明:本博客所有文章除特别声明外,均采用 署名-非商业性-相同方式共享 4.0 国际 (CC-BY-NC-SA-4.0) 许可协议。转载请注明出处!
- 02
- 使用Zadig从0到1实现持续交付平台07-19
- 03
- 基于Jira的运维发布平台07-19