使用PyInstaller打包Python程序

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 使用PyInstaller打包Python程序 PyInstaller介绍: PyInstaller是一个能将Python程序转换成单个可执行文件的程序, 操作系统支持Windows, Linux, Mac OS X, Solaris和AIX。

使用PyInstaller打包Python程序

PyInstaller介绍:

PyInstaller是一个能将Python程序转换成单个可执行文件的程序, 操作系统支持Windows, Linux, Mac OS X, Solaris和AIX。并且很多包都支持开箱即用,不依赖环境。

环境为windows7操作系统,python2.7.8 virtual environment

官网:https://github.com/pyinstaller/pyinstaller

详细步骤:

1. win7下面先安装这个依赖:pywin32,下载下来后切换到venv2.7,然后使用easy_install xxx.exe安装

2. pip安装PyInstaller:

1
pip install pyinstaller

3. 打包过程中可能会出现msvcp90.dll找不到的问题, 去http://cn.dll-files.com/msvcp90.dll.html下载第三个zip文件, 解压后放到C:\Windows\System32,如果是64位的还要放到C:\Windows\SysWOW64目录下。

4. 再次运行报MSVCR90.dll找不到,同理去http://cn.dll-files.com/MSVCR90.dll.html下载MSVCR90.dll, 放到C:\Windows\System32和C:\Windows\SysWOW64中。

5. 将你的整个程序先复制到某个临时文件夹下面,比如D:\tmp\core-wxpython,此目录下有个main.py是执行入口

6. 执行build命令,并添加必要的搜索路径,外加执行文件的图标:

1
2
cd D:\tmp\core-wxpython
pyinstaller -F -w -i d:\tmp\main.ico main.py

如果还想添加自定义的依赖库,就要加上-p参数:

1
pyinstaller -F -w -p D:\tmp\core-python\libs -i d:\tmp\main.ico main.py

参数说明:

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

注意的事情

1). 检查生成的\XXX\build\pyi.win32\XXX\warnXXX.txt(XXX是你的项目名)中, 是否缺少了必要的模块。如果有缺少的,那么去如上所述,添加必要的搜素路径, 使得pyinstaller在运行时,可以找到对应的模块并集成进来。

2). 此处我这里没有UPX,暂时没去折腾。估计是用UPX去压缩,压缩后所生成的exe文件的大小,会小得多。

7. 如果发现报错:pywintypes.error: (193, ‘LoadLibraryEx’… ) 原因是添加图标后缀必须是xxx.ico才行,重新去网上下载一个ico格式的图片,再次运行就好了。

8. 我测试了一个使用wxpython写的gui程序,源码里面引用了一张图片, 使用wx.Image(os.path.abspath(file/me.jpg), wx.BITMAP_TYPE_JPEG)来加载, 然后打包成exe后发现找不到图片了,报错。

解决办法:

第一步,在程序中将资源文件都放到一个单独的文件夹中,比如项目根目录下面的resources

第二步,修改程序中引用这些资源文件比如图片的代码:

1
2
3
4
5
6 7 
def resource_path(relative_path):  """定义一个读取相对路径的函数"""  if hasattr(sys, "_MEIPASS"):  base_path = sys._MEIPASS  else:  base_path = os.path.abspath(".")  return os.path.join(base_path, relative_path) 

然后每次在获取图片的时候,这么引用它的目录:

1
img = wx.Image(resource_path('resources/me.jpg'), wx.BITMAP_TYPE_JPEG) 

第三步,先运行第6步生成一个main.spec文件

第四步,修改main.spec文件:

1
2
3
4
5
6 7 8 9 10 11 12 13 14 15 16 17 18 
# -*- mode: python -*-
a = Analysis(['main.py'],  pathex=['d:\\tmp\\core-wxpython'],  hiddenimports=[],  hookspath=None,  runtime_hooks=None) pyz = PYZ(a.pure) exe = EXE(pyz,  a.scripts,  a.binaries,  a.zipfiles,  a.datas,  [('\\resources\\me.jpg','D:\\tmp\\core-wxpython\\resources\\me.jpg','DATA')],  name='main.exe',  debug=False,  strip=None,  upx=True,  console=True , icon='d:\\tmp\\main.ico') 

注意:我在a.datas下面添加了那行配置,具体的路径自己去修改下。

上面是添加单个文件,如果有多个文件,可以一个个的添加。不过如果文件多了话,那么就使用下面的方法:

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 
# -*- mode: python -*-
a = Analysis(['main.py'],  pathex=['d:\\tmp\\core-wxpython'],  hiddenimports=[],  hookspath=None,  runtime_hooks=None)  def extra_datas(mydir):  def rec_glob(p, files):  import os  import glob  for d in glob.glob(p):  if os.path.isfile(d):  files.append(d)  rec_glob("%s/*" % d, files)  files = []  rec_glob("%s/*" % mydir, files)  extra_datas = []  for f in files:  extra_datas.append((f, f, 'DATA'))   return extra_datas  # append the 'resources' dir a.datas += extra_datas('resources')  pyz = PYZ(a.pure) exe = EXE(pyz,  a.scripts,  a.binaries,  a.zipfiles,  a.datas,  name='main.exe',  debug=False,  strip=None,  upx=True,  console=True , icon='d:\\tmp\\main.ico') 

它会把某个指定的文件下的所有文件递归的添加到最终的包中。省去很多事情!

第五步,执行:pyinstaller D:\tmp\core-wxpython\main.spec

然后就大功告成了!!!在dist目录下面有个main.exe单独的可执行文件,打开它吧。^_^

如果在执行过程中出错,或者双击打开没任何反应。 可以先去掉-w参数后,在控制台窗口打开这个可执行文件,会输出详细出错信息去调试。

其他问题记录

1. 找不到pkg_resources

ImportError: No module named pkg_resources

解决办法是在安装pycrypto之前,先安装distribute库

1
curl https://svn.apache.org/repos/asf/oodt/tools/oodtsite.publisher/trunk/distribute_setup.py | python 

然后再安装windows下面对应的pycrypto库

1
2
# http://www.voidspace.org.uk/python/modules.shtml#pycrypto
easy_install http://www.voidspace.org.uk/downloads/pycrypto26/pycrypto-2.6.win-amd64-py2.7.exe 

2. 打包时加上-w选项去掉console时出错

不要在程序中使用任何print语句,或者是你将stdout重定向到一个日志、文件或任何其他非控制台地方。

最好的方法是利用日志功能,将输出定向到日志文件中去,在main函数开头添加如下代码:

1
2
3
4
5
import logging
import tempfile logging.basicConfig(level=logging.INFO,  filename=tempfile.TemporaryFile().name,  format='%(asctime)s %(message)s') 

用到logging的时候,需要配置日志到文件中,而不是console:

1
2
import logging
_LOGGING = logging.getLogger(__file__) 

3. pyinstaller用one file方式打包的程式如果有用到subprocess.Popen會有問題

问题参考:http://www.pyinstaller.org/ticket/597

最後找到的方法是 http://code.activestate.com/recipes/578300-python-subprocess-hide-console-on-windows/

建立一個隐藏窗口,就正常了~

最后用pyinstaller設one folder & no console打包都不跳出小窗口了

解决办法就是自定义一个subprocess_call函数来代替subprocess的call调用,不适用Popen了:

1
2
3
4
5
6 7 8 9 10 11 
def subprocess_call(*args, **kwargs):  # also works for Popen. It creates a new *hidden* window,  # so it will work in frozen apps (.exe).  if IS_WIN32:  _LOGGING.info('subprocess_call==IS_WIN32')  startupinfo = subprocess.STARTUPINFO()  startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW  startupinfo.wShowWindow = subprocess.SW_HIDE  kwargs['startupinfo'] = startupinfo  retcode = subprocess.call(*args, **kwargs)  return retcode 

调用方法:

1
exresult = subprocess_call(exe_command, shell=True) 

这个方法会等命令执行完成,返回值为0表示正常结束!

4. 打包后不能放到中文路径下执行 解决办法是下载安装PyInstaller的中文支持库,安装后再重新执行pyinstaller打包命令:

1
2
3
git clone https://github.com/dkw72n/pyinstaller.git python setup.py install pyinstaller -F -w -i d:\tmp\main.ico main.py
技术改变世界! --狂诗绝剑
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
2天前
|
存储 NoSQL 数据库连接
在Python程序中实现LevelDB的海量key的分批次扫描
通过本文的步骤,您可以在Python程序中实现对LevelDB海量key的分批次扫描。这样不仅能够有效地管理大规模数据,还可以避免一次性加载过多数据到内存中,提高程序的性能和稳定性。希望这篇指南能为您的开发工作提供实用的帮助。
43 28
|
21天前
|
安全 API C语言
Python程序的安全逆向(关于我的OPENAI的APIkey是如何被盗的)
本文介绍了如何使用C语言编写一个简单的文件加解密程序,并讨论了如何为编译后的软件添加图标。此外,文章还探讨了Python的.pyc、.pyd等文件的原理,以及如何生成和使用.pyd文件来增强代码的安全性。通过视频和教程,作者详细讲解了生成.pyd文件的过程,并分享了逆向分析.pyd文件的方法。最后,文章提到可以通过定制Python解释器来进一步保护源代码。
64 6
|
1月前
|
IDE 程序员 开发工具
Python编程入门:打造你的第一个程序
迈出编程的第一步,就像在未知的海洋中航行。本文是你启航的指南针,带你了解Python这门语言的魅力所在,并手把手教你构建第一个属于自己的程序。从安装环境到编写代码,我们将一步步走过这段旅程。准备好了吗?让我们开始吧!
|
14天前
|
Shell 开发工具 Python
如何在vim里直接运行python程序
如何在vim里直接运行python程序
|
2月前
|
存储 人工智能 数据挖掘
Python编程入门:打造你的第一个程序
本文旨在为初学者提供Python编程的初步指导,通过介绍Python语言的基础概念、开发环境的搭建以及一个简单的代码示例,帮助读者快速入门。文章将引导你理解编程思维,学会如何编写、运行和调试Python代码,从而开启编程之旅。
48 2
|
2月前
|
Python
在Python中,`try...except`语句用于捕获和处理程序运行时的异常
在Python中,`try...except`语句用于捕获和处理程序运行时的异常
62 5
|
2月前
|
存储 Python
Python编程入门:理解基础语法与编写简单程序
本文旨在为初学者提供一个关于如何开始使用Python编程语言的指南。我们将从安装Python环境开始,逐步介绍变量、数据类型、控制结构、函数和模块等基本概念。通过实例演示和练习,读者将学会如何编写简单的Python程序,并了解如何解决常见的编程问题。文章最后将提供一些资源,以供进一步学习和实践。
50 1
|
7月前
|
Python Windows
Python基础教程(第3版)中文版 第18章 程序打包 (笔记)
Python基础教程(第3版)中文版 第18章 程序打包 (笔记)
|
7月前
|
搜索推荐 区块链 开发者
【python程序打包教程】PyInstaller一键打包Python程序为独立可执行exe文件
【python程序打包教程】PyInstaller一键打包Python程序为独立可执行exe文件
|
8月前
|
Python
使用PyInstaller将Python应用程序打包成EXE文件
使用PyInstaller将Python应用程序打包成EXE文件
872 0