pyinstaller编译python脚本为单文件可执行文件遇到的问题

编译python脚本为单文件可执行文件(python3)

环境概况

1
2
3
系统:CentOS Linux release 7.5
python版本:3.6.1
注:已安装pip

安装pyinstaller
pip install pyinstaller pyinstaller --onefile testCsv.py #编译好的文件在dist目录下 ​

激动的开始做成可执行单文件,这是什么鬼…

1
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[root@magicYou signal]# pyinstaller --onefile testCsv.py
204 INFO: PyInstaller: 3.3.1
205 INFO: Python: 3.6.1
206 INFO: Platform: Linux-3.10.0-693.17.1.el7.x86_64-x86_64-with-centos-7.5.1804-Core
206 INFO: wrote /python/signal/testCsv.spec
209 INFO: UPX is not available.
210 INFO: Extending PYTHONPATH with paths
['/python/signal', '/python/signal']
210 INFO: checking Analysis
210 INFO: Building Analysis because out00-Analysis.toc is non existent
210 INFO: Initializing module dependency graph...
211 INFO: Initializing module graph hooks...
212 INFO: Analyzing base_library.zip ...
3827 INFO: running Analysis out00-Analysis.toc
3840 INFO: Caching module hooks...
3844 INFO: Analyzing /python/signal/testCsv.py
3867 INFO: Loading module hooks...
3868 INFO: Loading module hook "hook-encodings.py"...
3937 INFO: Loading module hook "hook-pydoc.py"...
3938 INFO: Loading module hook "hook-xml.py"...
4206 INFO: Looking for ctypes DLLs
4206 INFO: Analyzing run-time hooks ...
4213 INFO: Looking for dynamic libraries
4753 INFO: Looking for eggs
4753 INFO: Python library not in binary dependencies. Doing additional searching...
Traceback (most recent call last):
File "/usr/local/python3/bin/pyinstaller", line 11, in <module>
sys.exit(run())
File "/usr/local/python3/lib/python3.6/site-packages/PyInstaller/__main__.py", line 94, in run
run_build(pyi_config, spec_file, **vars(args))
File "/usr/local/python3/lib/python3.6/site-packages/PyInstaller/__main__.py", line 46, in run_build
PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
File "/usr/local/python3/lib/python3.6/site-packages/PyInstaller/building/build_main.py", line 791, in main
build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build'))
File "/usr/local/python3/lib/python3.6/site-packages/PyInstaller/building/build_main.py", line 737, in build
exec(text, spec_namespace)
File "<string>", line 16, in <module>
File "/usr/local/python3/lib/python3.6/site-packages/PyInstaller/building/build_main.py", line 213, in __init__
self.__postinit__()
File "/usr/local/python3/lib/python3.6/site-packages/PyInstaller/building/datastruct.py", line 161, in __postinit__
self.assemble()
File "/usr/local/python3/lib/python3.6/site-packages/PyInstaller/building/build_main.py", line 545, in assemble
self._check_python_library(self.binaries)
File "/usr/local/python3/lib/python3.6/site-packages/PyInstaller/building/build_main.py", line 629, in _check_python_library
raise IOError(msg)
OSError: Python library not found: libpython3.6.so.1.0, libpython3.6mu.so.1.0, libpython3.6m.so.1.0
This would mean your Python installation doesn't come with proper library files.
This usually happens by missing development package, or unsuitable build parameters of Python installation.

* On Debian/Ubuntu, you would need to install Python development packages
* apt-get install python3-dev
* apt-get install python-dev
* If you're building Python by yourself, please rebuild your Python with `--enable-shared` (or, `--enable-framework` on Darwin)

按照一贯做法,百度谷歌一波

尝试解决方案一:

搜来的原话是这样说的

1
2
大概意思就是pyinstaller报错找不到python动态库,也提示说升级python-dev。因为我是centos,各种yum install python-devel和yum install python-dev都不行,什么升级/重装python、sudo、su甚至重装系统都不行!!!我又必须在centos6.2环境下编译,如果我在其他高版本的环境下打包后拿到centos6.2就会报错,言归正传!其实处理起来很简单。只需要复制python安装目录下的动态库到系统地动态库目录即可。
cp -R /usr/local/python3.4/lib/* /usr/lib64/ 这样就搞定了!

我的是python3.6,要不就试试呗。

看了一下,python安装位置,没毛病,

1
cp -R /usr/local/python3.6/lib/* /usr/lib64/

再次生成可执行单文件,依然报错,问题一样,接着找解决办法

尝试解决方案二:

仔细看报错的信息,有这么一段很醒目:

1
2
3
4
5
6
7
SError: Python library not found: libpython3.6.so.1.0, libpython3.6mu.so.1.0, libpython3.6m.so.1.0
This would mean your Python installation doesn't come with proper library files.
This usually happens by missing development package, or unsuitable build parameters of Python installation.

* On Debian/Ubuntu, you would need to install Python development packages
* apt-get install python3-dev
* apt-get install python-dev

是在说我缺少了某个东西,让我安装python3-dev云云的。深入了解一下

1
2
3
4
5
6
7
8
linux发行版通常会把类库的头文件和相关的pkg-config分拆成一个单独的xxx-dev(el)包.    //pkg=package,包裹

以python为例, 以下情况你是需要python-dev的

你需要自己安装一个源外的python类库, 而这个类库内含需要编译的调用python api的c/c++文件 //如:安装使用WiringpisPi库需要python-dev
你自己写的一个程序编译需要链接libpythonXX.(a|so)
(注:以上不含使用ctypes/ffi或者裸dlsym方式直接调用libpython.so)
其他正常使用python或者通过安装源内的python类库的不需要python-dev.

后再来找一一个靠谱的回答

原话是这样说的:

1
2
3
4
5
You must install python-dev for your python's version
for example:
Debian/Ubuntu - Python 2.7 ---> python2.7-dev
CentOs/RedHat - Python 3.4 ---> python34-devel
CentOs/RedHat - Python 2.7 ---> python27-devel

各个python版本对应的python-dev版本,推测我的是python36-devel,动手试试

1
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
[root@magicYou signal]# yum install python36-devel
已加载插件:fastestmirror, langpacks
Repository base is listed more than once in the configuration
Repository updates is listed more than once in the configuration
Repository extras is listed more than once in the configuration
Repository centosplus is listed more than once in the configuration
Loading mirror speeds from cached hostfile
正在解决依赖关系
--> 正在检查事务
---> 软件包 python36-devel.x86_64.0.3.6.5-3.el7 将被 安装
--> 正在处理依赖关系 python36-libs(x86-64) = 3.6.5-3.el7,它被软件包 python36-devel-3.6.5-3.el7.x86_64 需要
--> 正在处理依赖关系 python36 = 3.6.5-3.el7,它被软件包 python36-devel-3.6.5-3.el7.x86_64 需要
--> 正在处理依赖关系 python(abi) = 3.6,它被软件包 python36-devel-3.6.5-3.el7.x86_64 需要
......
......
python36-devel.x86_64 0:3.6.5-3.el7

作为依赖被安装:
dwz.x86_64 0:0.11-3.el7
perl-srpm-macros.noarch 0:1-8.el7
python-rpm-macros.noarch 0:3-22.el7
python-srpm-macros.noarch 0:3-22.el7
python36.x86_64 0:3.6.5-3.el7
python36-libs.x86_64 0:3.6.5-3.el7
redhat-rpm-config.noarch 0:9.1.0-80.el7.centos

完毕!

再次尝试pyinstaller生成可执行单文件

1
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
39
40
41
42
root@magicYou signal]# pyinstaller --onefile testCsv.py
234 INFO: PyInstaller: 3.3.1
234 INFO: Python: 3.6.1
235 INFO: Platform: Linux-3.10.0-693.17.1.el7.x86_64-x86_64-with-centos-7.5.1804-Core
236 INFO: wrote /python/signal/testCsv.spec
239 INFO: UPX is not available.
240 INFO: Extending PYTHONPATH with paths
['/python/signal', '/python/signal']
240 INFO: checking Analysis
240 INFO: Building Analysis because out00-Analysis.toc is non existent
240 INFO: Initializing module dependency graph...
241 INFO: Initializing module graph hooks...
243 INFO: Analyzing base_library.zip ...
3891 INFO: running Analysis out00-Analysis.toc
3904 INFO: Caching module hooks...
3908 INFO: Analyzing /python/signal/testCsv.py
3933 INFO: Loading module hooks...
3934 INFO: Loading module hook "hook-encodings.py"...
4006 INFO: Loading module hook "hook-pydoc.py"...
4007 INFO: Loading module hook "hook-xml.py"...
4292 INFO: Looking for ctypes DLLs
4292 INFO: Analyzing run-time hooks ...
4299 INFO: Looking for dynamic libraries
4864 INFO: Looking for eggs
4864 INFO: Python library not in binary dependencies. Doing additional searching...
4901 INFO: Using Python library /usr/lib64/libpython3.6m.so.1.0
4905 INFO: Warnings written to /python/signal/build/testCsv/warntestCsv.txt
4936 INFO: Graph cross-reference written to /python/signal/build/testCsv/xref-testCsv.html
4949 INFO: checking PYZ
4949 INFO: Building PYZ because out00-PYZ.toc is non existent
4949 INFO: Building PYZ (ZlibArchive) /python/signal/build/testCsv/out00-PYZ.pyz
5320 INFO: Building PYZ (ZlibArchive) /python/signal/build/testCsv/out00-PYZ.pyz completed successfully.
5323 INFO: checking PKG
5323 INFO: Building PKG because out00-PKG.toc is non existent
5323 INFO: Building PKG (CArchive) out00-PKG.pkg
10523 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
10526 INFO: Bootloader /usr/local/python3/lib/python3.6/site-packages/PyInstaller/bootloader/Linux-64bit/run
10526 INFO: checking EXE
10526 INFO: Building EXE because out00-EXE.toc is non existent
10526 INFO: Building EXE from out00-EXE.toc
10526 INFO: Appending archive to ELF section in EXE /python/signal/dist/testCsv
10555 INFO: Building EXE from out00-EXE.toc completed successfully.

问题解决,很棒很棒!

续集

后来又在centos6.8,发现上述办法不能解决这个问题

Centos6.8上如下

1
2
3
4
5
6
7
8
9
[root@magicYou /]# yum install python36-devel
已加载插件:fastestmirror
设置安装进程
Loading mirror speeds from cached hostfile
base | 3.7 kB 00:00
extras | 3.4 kB 00:00
updates | 3.4 kB 00:00
No package python36-devel available.
错误:无须任何处理

后来又在centos7.2 上看了一下:

1
2
3
4
5
6
7
8
9
[root@VM_0_12_centos ~]# yum install python36-devel
已加载插件:fastestmirror, langpacks
epel | 3.2 kB 00:00:00
extras | 3.4 kB 00:00:00
os | 3.6 kB 00:00:00
updates | 3.4 kB 00:00:00
Loading mirror speeds from cached hostfile
软件包 python36-devel-3.6.6-1.el7.x86_64 已安装并且是最新版本
无须任何处理

为啥不一样呢,依然解决不了问题。后来在一个角落找到一个靠谱的,如下:

1
2
3
4
5
6
7
8
9
10
I have solved this in the way below:
1st. check your system if it has libpython3.4m.so.1.0. If yes, go to step 2nd. If no, download it(I'm using anaconda python, so I have it in anaconda folder.)
2nd. sudo cp /folder/to/your/libpython3.4m.so.1.0 /usr/lib

# 翻译一下

我用下面的方法解决了这个问题:
1. 检查系统是否具有libpython3.4.so.1.0。如果有,请转到步骤2。如果没有,下载它(我使用的是anaconda python,所以我把它放在anaconda文件夹中)。
2. sudo cp /folder/to/your/libpython3.4.so.1.0 /usr/lib

比葫芦画瓢,find一下,还真找到了

1
find / -name libpython3.6mu.so.1.0
1
cp /folder/to/your/libpython3.6mu.so.1.0 /usr/lib

再次解决问题,十分坎坷

总结:

  1. pyinstaller的问题在不同的系统上都不一样;
  2. 还有一个比较严重的问题就是在高版本的centos上生成的可执行单文件在低版本上可能无法运行,我自己的第一个虚拟机是centos7.2费了老劲搞好环境生成单文件放在生产环境centos6.8报错,查找问题是说一个系统的库版本太高导致;