用 Pyinstaller 模块将 Python 程序打包成 exe 文件(全网最全面最详细)(三)

简介: 用 Pyinstaller 模块将 Python 程序打包成 exe 文件(全网最全面最详细)(三)

2、修改文件打开函数

这里有三种方法,前两种是我的方法,最后一种是网上别人的方法。

① 引入特定的模块

这个模块的代码很简单,放在下面,一定要将模块命名为 _.py,并在引用其他第三方模块之前就引用它,但又一定要在下划线开头的模块之后引用(否则会有 BUG),它在主 Python 文件里引用一次即可(其他的文件不用引用)!它可以将 open 函数改成我们想要的,而且原来的代码还完全不用修改!

import builtins
def wrapper(function):
    def _open(*args, **kw):
        """ 修改路径 """
        _args = list(args)
        _args[0] = __file__[:-4] + args[0]
        if kw.get('file'):
            kw['file'] = __file__[:-4] + kw['file']
        return function(*_args, **kw)
    return _open
setattr(builtins, 'open', wrapper(open))

这里的 __file__ 是 Python 文件的属性,是一个字符串,为该文件的绝对路径,不管该文件在哪里,__file__ 都是对应的绝对路径。然后我们用写一个 wrapper 函数充当装饰器,将内置的 open 函数包装一下。再引入 builtins 模块(内置函数和类的模块),给其添加一个名为 open 新属性以覆盖原来的 open 函数,并对该项目整体生效即可!


这种方法的好处在于,它只需要在主文件里引用一次即可,其他的什么都不用改!(④ 特别注意 里的除外)

② 自己手动修改 open 函数修改路径

这个修改是在源代码中修改的(每一个用到了 open 函数的 Python 文件都要改一次),目的就是要让相对路径变成会根据主 Python 文件的路径而变化的绝对路径。修改的装饰器如下:

# 编写装饰器
def wrapper(function):
    def _open(*args, **kw):
        """ 修改路径 """
        args_list = list(args)
        key = '/'.join(__file__.split('\\')[:-1]) + '/'
        args_list[0] = key + args[0]
        if kw.get('file'):
            kw['file'] = key + kw['file']
        return function(*args_list, **kw)
    return _open
# 装饰内置函数open
open = wrapper(open)

把这段代码写在文件的开头即可(或者说在使用open函数之前)。

③ 网友的其他方法

他们就是写了这样一个函数来代替 open,也是手动修改的 open 函数,不得不说,看起来有点麻烦(每个用了 open 函数的 Python 文件都要引入 os 和 sys 模块)。

import os
import sys
def get_resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)

其他的都是一样的。

④ 特别注意

这里还要提一下,无论是前面的哪一种方法,只要你使用了参数为路径的其他函数时,也要改一下,其实就是在相对路径前面加上方法②中的 key 即可。


其实直接方法③来代替也可以,但是功能上容易出错,而且如果 Python 文件较多,那么每个 Python 文件都这样引用两个模块(sys 和 os),看起来比较麻烦。


当我们使用了 tkinter 模块的时候,PhotoImage 类就是要这样写的一个例子(其中的 __init__ 方法用到了路径):

class PhotoImage(tkinter.PhotoImage):
    def __init__(self, *args, **kw):
        if kw.get('file'):
            key = '/'.join(__file__.split('\\')[:-1]) + '/'
            kw['file'] = key + kw['file']
        tkinter.PhotoImage.__init__(self, *args, **kw)

这个代码就要写在使用 PhotoImage 的开头,后续调用时就用这个 PhotoImage,使用其他模块时,遇到参数为路径的函数或类,都要这样修改。

最后一步,和之前的方法一样,打包你的程序即可!

打包实战

我这里以一个我的半成品为例,进行打包。项目是一个图形化界面的程序。我们要将其打包成只含有一个 exe 的文件。

打包方式的选择

我的项目里面包含多个 Python 文件,要用多 Python 文件打包方式;

项目比较大,为节省打包时间,并追求极致的 exe 大小,采用虚拟环境打包方式;

项目含有资源文件夹,采用包含资源文件的打包方式。

打包方式选择好了,开始打包!

打包全过程

项目全部文件(蓝色背景的是主文件)项目文件

包含四个 Python 文件、一个资源文件夹(res),资源文件夹里面又包含了一些子文件夹和 json 文件。

第一步:启动 Anaconda Prompt,切换至目标文件夹路径位置

cd C:\Users\小康\Desktop\SuperGameLauncher

第二步:启动虚拟环境(我的是一个纯净的、第三方包只有 Pyinstaller 的环境)

conda activate e1

启动虚拟环境切换至目标文件夹路径位置

第二步:启动虚拟环境(我的是一个纯净的、第三方包只有 Pyinstaller 的环境)

conda activate e1

启动虚拟环境

第四步:引入 _.py 模块(我的程序用到了大量 open 函数且涉及多文件)

_.py 自定义模块

引入 _ 模块

处理特殊的情况(tkintertools 模块里面有参数为路径的类):

处理特殊情况

第五步:编辑 spec 文件

修改图中标识的两处地方(_.py 不要忘记了)。

编辑 spec 文件

第六步:打包项目(注意这里的对象是 spec 文件)

Pyinstaller SuperGameLauncher.spec

准备打包

打包成功!

打包成功

第七步:检验打包效果

找到项目中的 dist 文件夹,打开后会有一个 exe 文件。对于我这个项目而言,这已经是非常小的大小了(50.8MB),毕竟资源文件就有 42.2MB,也就是说,除去资源文件,源代码占用的大小为 8.6MB!怎么样,是不是很不错呢?

dist 文件夹

双击运行!

成功运行

目录
相关文章
|
7天前
|
计算机视觉 Python
如何使用Python将TS文件转换为MP4
本文介绍了如何使用Python和FFmpeg将TS文件转换为MP4文件。首先需要安装Python和FFmpeg,然后通过`subprocess`模块调用FFmpeg命令,实现文件格式的转换。代码示例展示了具体的操作步骤,包括检查文件存在性、构建FFmpeg命令和执行转换过程。
31 7
|
1月前
|
开发者 Python
Python中__init__.py文件的作用
`__init__.py`文件在Python包管理中扮演着重要角色,通过标识目录为包、初始化包、控制导入行为、支持递归包结构以及定义包的命名空间,`__init__.py`文件为组织和管理Python代码提供了强大支持。理解并正确使用 `__init__.py`文件,可以帮助开发者更好地组织代码,提高代码的可维护性和可读性。
46 2
|
1月前
|
中间件 Docker Python
【Azure Function】FTP上传了Python Function文件后,无法在门户页面加载函数的问题
通过FTP上传Python Function至Azure云后,出现函数列表无法加载的问题。经排查,发现是由于`requirements.txt`中的依赖包未被正确安装。解决方法为:在本地安装依赖包到`.python_packages/lib/site-packages`目录,再将该目录内容上传至云上的`wwwroot`目录,并重启应用。最终成功加载函数列表。
|
2月前
|
Java Python
> python知识点100篇系列(19)-使用python下载文件的几种方式
【10月更文挑战第7天】本文介绍了使用Python下载文件的五种方法,包括使用requests、wget、线程池、urllib3和asyncio模块。每种方法适用于不同的场景,如单文件下载、多文件并发下载等,提供了丰富的选择。
|
4月前
|
SQL JSON 关系型数据库
n种方式教你用python读写excel等数据文件
n种方式教你用python读写excel等数据文件
|
6月前
|
存储 Python 内存技术
python WAV音频文件处理—— (1)读写WAV文件
python WAV音频文件处理—— (1)读写WAV文件
166 14
|
7月前
|
数据挖掘 索引 Python
Python 读写 Excel 文件
Python 读写 Excel 文件
171 0
|
Python
python读写execle文件数据
python读写execle文件数据
|
7月前
|
存储 JSON JavaScript
Python中读写(解析)JSON文件的深入探究
Python中读写(解析)JSON文件的深入探究
212 0
|
7月前
|
XML 安全 API
Python读写XML文件:深入解析与技术实现
Python读写XML文件:深入解析与技术实现
239 0

热门文章

最新文章