Pyinstaller打包,彻底解决图片、数据路径问题!
↑ 关注 + 星标 ,每天学Python新技能
后台回复【大礼包】送你Python自学大礼包
Pyinstaller打包,解决图片、数据路径问题!
很多网友碰到找不到文件的问题,都是因为对Python读取文件路径的知识理解不深。本周的每天3分钟,我们就主要围绕路径问题。
如果要把Python打包成一个可执行文件,或者一个文件夹,最常用的方式是pyinstaller。
使用方法很简单,但是很多麦友会碰到路径问题:如果代码中需要用到图片或数据文件,打包后执行会失败!
咱们今天就来解决这个问题。篇幅有限,我演示一个简单的例子,并指出解决更复杂的问题的方向。
案例介绍
本例子将要打包如下文件结构:
--058
--058.py
--058.txt
文件夹058下有两个文件:058.py和058.txt。其中058.py
源代码如下:
import pathlib
folder = pathlib.Path(__file__).parent.resolve()
print(f'当前python文件所在目录:{folder}')
with open(f'{folder}/058.txt') as file:
print(file.read())
也就是说058.py文件需要用到058.txt文件。
直接运行,会打印出数据文件的内容:
当前python文件所在目录:/Users/maishu/git/wx_maishucode/code/058
跟麦叔搞定路径问题
我们的任务是:打包成一个exe文件,可以分发给没有Python,不懂Python的人使用。
“以下例子用Mac做演示,在Windows或Linux下也是一样的。
安装pyinstaller
pyinstaller是一个Python的模块,我们先来安装它。
在命令行下运行:
python -m pip install pyinstaller
执行结果如下,安装成功:
maishu@msmacbook 058 % python -m pip install pyinstaller
Collecting pyinstaller
Downloading pyinstaller-4.9-py3-none-macosx_10_13_universal2.whl (1.6 MB)
|████████████████████████████████| 1.6 MB 152 kB/s
Collecting pyinstaller-hooks-contrib>=2020.6
Downloading pyinstaller_hooks_contrib-2022.2-py2.py3-none-any.whl (223 kB)
|████████████████████████████████| 223 kB 117 kB/s
Collecting macholib>=1.8
Downloading macholib-1.15.2-py2.py3-none-any.whl (37 kB)
Requirement already satisfied: setuptools in /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages (from pyinstaller) (57.4.0)
Collecting altgraph
Downloading altgraph-0.17.2-py2.py3-none-any.whl (21 kB)
Installing collected packages: altgraph, pyinstaller-hooks-contrib, macholib, pyinstaller
Successfully installed altgraph-0.17.2 macholib-1.15.2 pyinstaller-4.9 pyinstaller-hooks-contrib-2022.2
WARNING: You are using pip version 21.2.3; however, version 22.0.3 is available.
You should consider upgrading via the '/Library/Frameworks/Python.framework/Versions/3.10/bin/python3 -m pip install --upgrade pip' command.
其中的WARNING无伤大雅,先不用管。
打包失败
现在我们来尝试打包。用pyinstaller的打包过程是很简单的。
去到058所在的文件夹,运行如下命令:
pyinstaller 058.py
会发现058文件夹下多了很多内容:
其中dist目录就是打包好的内容所在文件夹。dist是distribution的缩写,中文是发布的意思。
进去看看,会发现dist里面又有一个058文件夹,里面放着很多内容,包括了python解释器等。
理论上,我们把整个058文件夹发给别人。
他们运行其中的058可执行文件(图中第一个),就可以正确执行我们的程序。
现在我去双击一下058文件,得到的结果是:
maishu@msmacbook ~ % /Users/maishu/git/wx_maishucode/code/058/dist/058/058 ; exit;
当前python文件所在目录:/Users/maishu/git/wx_maishucode/code/058/dist/058
Traceback (most recent call last):
File "058.py", line 5, in
FileNotFoundError: [Errno 2] No such file or directory: '/Users/maishu/git/wx_maishucode/code/058/dist/058/058.txt'
[8404] Failed to execute script '058' due to unhandled exception!
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
运行失败了:FileNotFoundError,因为数据文件没有打包进去。
打包成功:--add-data选项
我们前面用了最简单的打包命令,它会把python程序打包进去,不会复制数据,当然会报错了。
实际上pyinstaller可以支持很多命令选项,我们现在重新打包一次,加一个选项:
pyinstaller --add-data "058.txt:." 058.py
这里添加了--add-data "058.txt:."
。解释一下:
--add-data表示后面要添加数据文件 058.txt是要添加的数据文件,它后面的冒号以及后面的点 .
表示把这个文件添加到当前目录下。也就是说添加文件是成对出现,前面是要添加的文件,后面是添加的目标目录,中间用冒号隔开。 可以添加多个文件,用分号隔开。
运行上面命令,会发现dist目录下多了数据文件:
然后去运行058可执行文件:
maishu@msmacbook ~ % /Users/maishu/git/wx_maishucode/code/058/dist/058/058 ; exit;
当前python文件所在目录:/Users/maishu/git/wx_maishucode/code/058/dist/058
跟麦叔搞定路径问题
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
成功了!!
打成独立的文件:--onefile
上面是打包成了一个文件夹,发送给别人还是有点麻烦的。我们也可以直接打包成一个单独的文件:
pyinstaller --add-data "058.txt:." --onefile 058.py
我们加了--onefile
选项,表示打包成1个独立的文件。
运行后发现dist下面干净多了:
运行一下,也能成功执行:
maishu@msmacbook ~ % /Users/maishu/git/wx_maishucode/code/058/dist/058 ; exit;
当前python文件所在目录:/private/var/folders/jw/ldvymnfj1zbbmngx3p8_zl_m0000gn/T/_MEIMaXGJM
跟麦叔搞定路径问题
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
解决更复杂的问题之路
pyinstaller有很多选项,我们在解决问题的时候可能会碰到更复杂的问题,我们3分钟讲不完。
如果你希望我更深入讲解,可以转发,点赞,嘻嘻。如果阅读和评论多,我可以考虑后续再出一个Pyinstaller终结者深度文章。
但是这里我就先指明几个方向,帮助你更有效的研究:
pyinstaller的官网上有很细致的讲解:https://pyinstaller.readthedocs.io/en/stable/spec-files.html。英语不好也可以用谷歌翻译。
pyinstaller打包的时候会首先生成一个spec文件,我们可以手工去修改这个文件,下次打包指定用这个文件。它的好处是:里面可以写更复杂的选项,也可以重录利用。
spec文件的内容例子:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['058.py'],
pathex=[],
binaries=[],
datas=[('058.txt', '.')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='058',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='058')
好啦,今天就聊到这里,如果对你有帮助,请帮忙转发。谢谢!
“新的一年,想加速Python学习,获得专业的指导,30天学会一门技能!
欢迎参加麦叔Python实战训练营,入门营,爬虫营,办公自动化营同步开放。
详情点这里:麦叔Python训练营
如果你希望我更新某个特定小知识,欢迎给我留言。
推荐阅读
您看此文用 分 秒,转发只需1秒哦~