QT与Python混合编程(二):使用pyinstaller打包Python程序

Python程序打包一直以来就是一个比较困难的话题,原因便在于Python程序中可能包含多个第三方支持库,如果没有较好的打包方法,很可能需要逐一对所用到的支持库进行添加,十分费时费力,还很有可能会出现遗漏。而pyinstaller则是针对这一问题的一个比较好的解决方法。

pyinstaller在网上已有许多教程,关于其的基本操作在网络上很容易可以找到,这里对其安装或使用的一些基础方法不再进行介绍,只针对笔者在使用过程中遇到的一些问题及相应的解决方法进行介绍:

1.pyinstaller打包的方式选择

打包的方式选择很多,而我使用的比较多的是以下两种,一种是:

pyinstaller -D -w test.py

另外一种是:

pyinstaller -F -w test.py

这两种方法的不同之处在于,第一种方法最终生成了一个包含所有必需文件的文件夹,而第二种方法则是生成了一个exe文件,前者文件众多且文件较大,后者只有一个文件且文件较小,理论上使用第二种方法较好。但是,文件打包之后往往会被部署到新的客户机上,客户机上的运行环境与开发环境往往差距较大,甚至于有的客户机近似于裸机,未配置任何必须的运行库。这时候,单一的exe文件往往无法运行成功,而打包生成文件夹的方式可以运行。就拿一个比较简单的例子来说,将程序部署到一个未安装python的客户机上,第一种方法可以正常运行,而第二种方法生存的exe文件往往运行失败。

2.打包生成的exe文件的调试

pyinstaller打包生成的文件不一定是正确的,常常出现打包成功之后,生成的exe文件无法正常运行的情况,这时就需要对exe文件进行调试,确定问题所在,而这时就不能直接双击exe文件运行了,应该选择命令行模式(打包时将-w改为-c),这时的命令行窗口也往往一闪而过,根本无法看清错误代码。因此,可以在cmd命令行窗口中进入exe文件所在的文件夹,之后在命令行中直接运行exe即可(即针对test.exe而言,在命令行中直接输入test即可),这时便可在cmd中获得exe文件的相关错误信息。

3.exe文件的错误分析

笔者仅针对自己所遇到的一些错误信息进行分析:

(1)ModuleNotFoundError:No module named ‘queue’

这类错误往往较易解决,因为涉及的是python自带的一些系统库,只需在源文件(test.py)的开头加上import queue即可。

(2)FileNotFoundError:[Errno 2] No such file or directory:‘’

很明显该类错误的成因在于程序未在指定位置找到所需的文件。根据提示可知,该类文件大多为第三方库的一些文件,即pyinstaller在打包时明显有所遗漏,但是很快又发现,并不是所有的第三方库在打包时都会出现这种情况,打包含有numpy、pandas或者matplotlib等库时均未出现这种情况。而其解决方法也分为两种:

a.在生成的当前目录下将所需的第三方库放在根目录下,这是比较容易想到的解决方法,但是治标不治本,以后每次打包时都需要手动添加文件夹过于繁琐;

b.根本性的解决方法在于使得pyinstaller能够找到对应库,由上述描述可知,只有在一部分库身上会出现这类问题,进一步分析,在打包过程中出现了以下代码:

QT与Python混合编程(二):使用pyinstaller打包Python程序_第1张图片

即pyinstaller是通过相应的hook文件进行第三方库的查找,查找对应文件所在位置:E:\Program Files\Python\Lib\site-packages\PyInstaller-3.4-py3.7.egg\PyInstaller\hooks,文件夹内容如下:

QT与Python混合编程(二):使用pyinstaller打包Python程序_第2张图片

打开hook-numpy.py,代码如下:

# -----------------------------------------------------------------------------
# Copyright (c) 2013-2018, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
# -----------------------------------------------------------------------------
import os
import glob
from PyInstaller.compat import is_win
from PyInstaller.utils.hooks import get_module_file_attribute

# if we bundle the testing module, this will cause
# `scipy` to be pulled in unintentionally but numpy imports
# numpy.testing at the top level for historical reasons.
# excludedimports = collect_submodules('numpy.testing')

binaries = []

# package the DLL bundle that official numpy wheels for Windows ship
if is_win:
    dll_glob = os.path.join(os.path.dirname(
        get_module_file_attribute('numpy')), 'extra-dll', "*.dll")
    if glob.glob(dll_glob):
        binaries.append((dll_glob, "."))

只是简单的模块导入相关操作,查找资料,新建对应aliyunsdkcore模块的导入文件,即新建hook-aliyunsdkcore.py文件,代码如下:

from PyInstaller.utils.hooks import collect_data_files
     
datas = collect_data_files("aliyunsdkcore")

将该文件放到site-packages\PyInstaller-3.4-py3.7.egg\PyInstaller\hooks文件夹里,即可保证使用,最后成功生成所需文件。再重新进行pyinstaller的打包工作,即可获得满足使用要求的exe打包文件。

你可能感兴趣的:(QT与Python混合编程)