Pyinstaller打包,彻底解决图片、数据路径问题!

共 5600字,需浏览 12分钟

 ·

2022-03-04 14:35

↑ 关注 + 星标 ,每天学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. 不可思议!乌克兰国防军队的系统账号和密码分别是 admin 和 123456!

  2. 又一款超酷的可视化神器:cutecharts

  3. 消息称腾讯微信试行“1065”工作制,晚 18 点强制下班?

  4. 爬取网站内容,合并Excel数据…推荐一个自动化办公神器!


您看此文用   分  秒,转发只需1秒哦~

浏览 170
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报