前言

本文讲解:脚本打包exe: win/mac【终端】



文章目录

  • 前言
  • 一、exe打包流程
  • 二、exe打包案例
  • 1.新建工程
  • 2.新建python文件
  • 3.添加并查看依赖包
  • 4.安装打包工具
  • 5.打包——打包成多文件
  • 6.打包——打包成单文件
  • 6.打包命名
  • 三、打包时路径问题
  • 四、关于模块的问题
  • 1. 静态导入模块
  • 2. 动态导入模块
  • 总结



一、exe打包流程

第三方模块

pip install pyinstaller

注意事项:

  • 支持mac、win (windows建议使用python3.6.8)。
  • 配合虚拟环境打包。

1.在mac系统上开发(为他这个程序创建一个虚拟环境) bili
2.开发…
3.开发完毕后 pip freeze > reqirements.txt
4.打开win虚拟机
5.创建虚拟环境bili
6.安装项目依赖 pip install -r reqirements.txt
7.安装pyinstaller pyinstaller -FXXXXX

产出:哗哩哗哩.exe

1.创建虚拟环境+项目bili
2.开发
3.安装pyinstaller pyinstaller -FXXXXX

产出:哗哩哗哩.exe

二、exe打包案例

1.新建工程

添加位置以及虚拟环境

gui python 打包命令 python打包教程_python

2.新建python文件

gui python 打包命令 python打包教程_虚拟环境_02


并在.py文件中输入内容,比如

import time

print("欢迎使用***系统")

text = input("请输入信息:")
print(text)

time.sleep(5)

3.添加并查看依赖包

比如 安装 requests

pip install requests

gui python 打包命令 python打包教程_gui python 打包命令_03

若需要看已经安装的第三方依赖包

pip freeze > requirements.txt

在requirements.txt中就可以看到已经安装好的依赖包

gui python 打包命令 python打包教程_学习_04


至此程序开发完成。

4.安装打包工具

先安装pyinstaller

pip install pyinstaller

安装成功后,将终端关闭再打开一次就有pyinstaller命令了。

gui python 打包命令 python打包教程_学习_05


然后就可以基于pyinstaller 对.py文件进行打包。

5.打包——打包成多文件

(1)打包成多文件

pyinstaller -D app.py #app.py为py文件名称,自行匹配更改

成功后生成三个新文件

gui python 打包命令 python打包教程_依赖包_06

.spec文件 配置文件
.build文件 编译过程中产出的代码(没啥用)
.dist文件 最终打完包的结果

(2)查看打包结果

在文件夹中可以看到app.exe文件,点击即可运行。

gui python 打包命令 python打包教程_依赖包_07

运行结果

gui python 打包命令 python打包教程_学习_08


5秒后自动关闭。

6.打包——打包成单文件

上述打包方式,打包后文件夹内形成多个文件,不利于客户查找。

(1)打包成单文件

pyinstaller -F app.py #app.py为py文件名称,自行匹配更改

成功后dist文件中只有app.exe一个文件了

gui python 打包命令 python打包教程_学习_09

(2)⚠️注意
无论哪种打包方式,若代码有错时,程序会立刻终止退出。如果想看程序的报错,要先打开终端,在输入exe文件的路径即可。

win终端打开方式:

在电脑搜索框输入“运行”进行搜索,并打开。

gui python 打包命令 python打包教程_学习_10


gui python 打包命令 python打包教程_依赖包_11

输入cmd执行

gui python 打包命令 python打包教程_虚拟环境_12

6.打包命名

pyinstaller -F app.py -n 我是名字

运行后,exe就是我们所设的名字。

gui python 打包命令 python打包教程_学习_13

打包的其他操作可以参考pyinstaller的说明,如-i 可以添加图标等。根据需要自己更改。

gui python 打包命令 python打包教程_python_14

三、打包时路径问题

当程序中存在打开本地文件时,路径是一个要特别注意的点。

(1)引入绝对路径

例如在目录中新建一个account.txt文件

gui python 打包命令 python打包教程_gui python 打包命令_15


在读取本地文件时,不建议写成with open("account.txt", mode='r', encoding='utf-8') as f:这种格式,很容易出问题。

一般使用os获取文件的绝对目录

import os

v = os.path.abspath(__file__)  #.py文件的绝对目录
Baes_Dir = os.path.dirname(os.path.abspath(__file__) ) #.py文件上一层的绝对目录
print(Baes_Dir)

然后根据绝对目录获取文件

import time
import os

Baes_Dir = os.path.dirname(os.path.abspath(__file__))  # .py文件上一层的绝对目录

#print(Baes_Dir)

print("---欢迎使用***系统---")

with open(os.path.join(Baes_Dir, "account.txt"), mode='r', encoding='utf-8') as f:
    data = f.read().strip()
print(data)

time.sleep(5)

(2)注意事项

按照上述方法打开外部文件时

  • 多文件打包,不会报错
  • 单文件打包,会报错

为什么会报错? 解析到临时目录问题。

解决方法如下:
方法一:使用sys.argv

import sys

#Baes_Dir = os.path.dirname(os.path.abspath(__file__))
Baes_Dir = os.path.dirname(os.path.realpath(sys.argv[0]))

打包后不会报错。

方法二:frozen

在官方文档中

gui python 打包命令 python打包教程_gui python 打包命令_16

import sys
if getattr(sys,'frozen',False):
	print ( ' running in a PyInstaller bundle ' )
else:
	print ( ' running in a normal Python process ' )

可以将咱们的代码改为

import time
import os
import sys

v = os.path.abspath(__file__)  # .py文件的绝对目录

# BASE_Dir = os.path.dirname(os.path.abspath(__file__))  # .py文件上一层的绝对目录

if getattr(sys, 'frozen', False):
    BASE_Dir = os.path.dirname(sys.executable)
else:
    BASE_Dir = os.path.dirname(os.path.abspath(__file__))

print("---欢迎使用***系统---")

with open(os.path.join(BASE_Dir, "account.txt"), mode='r', encoding='utf-8') as f:
    data = f.read().strip()
print(data)

time.sleep(5)

四、关于模块的问题

现在删掉打包的文件以及txt等文件,只留下app.py文件。

假设 程序中有其他依赖py文件,打包会出现什么情况?

1. 静态导入模块

例如:

新建一个目录,命名为utils,在该目录下,新建db.py和encrypt.py

gui python 打包命令 python打包教程_学习_17


在db.py和encrypt.py中定义两个函数

gui python 打包命令 python打包教程_依赖包_18


gui python 打包命令 python打包教程_python_19


并在主函数中调用

gui python 打包命令 python打包教程_gui python 打包命令_20


现在再打包,成功后,运行app.exe能看到程序运行正常。

gui python 打包命令 python打包教程_gui python 打包命令_21

下一个问题是
如果依赖包中又有另外的依赖包,打包会成功吗?

例如

在utils目录下,再新建一个xx.py文件,并定义函数。

gui python 打包命令 python打包教程_python_22

然后在db.py中导入xx函数

gui python 打包命令 python打包教程_虚拟环境_23


这样就变成app.py文件依赖db文件,db文件又依赖于xx文件。

现在再打包,完成后打开app.exe。可以发现,程序仍然可以运行成功。

gui python 打包命令 python打包教程_虚拟环境_24

至此,静态导入模块都不会有问题,会自动找到关联的依赖包,一起打包好。

2. 动态导入模块

但是,如果遇到那种动态导入模块的代码时,就无法找到关联的包

例如:

在utils目录下,新建card.py文件,并定义函数

gui python 打包命令 python打包教程_虚拟环境_25


然后在主函数中动态调用

gui python 打包命令 python打包教程_gui python 打包命令_26


这种情况下打包后会报错。

解决方法

在刚才打包后生成的.spec配置文件中,加入我们的所需的模块。

gui python 打包命令 python打包教程_虚拟环境_27


之后不能用pyinstaller -F app.py命令打包,因为会生成一个新的配置文件,覆盖掉我们已经修改的文件。

要使用pyinstaller -F app.spec命令,通过spec文件来进行打包。

报错makespec options not valid when a.spec file is given的话,
改用pyinstaller app.spec即可

打包成功后,点击app.exe文件就可以正常运行了。

gui python 打包命令 python打包教程_依赖包_28


总结

以上就是今天要讲的内容,本文介绍了python打包的一般步骤以及会遇到的问题相应的解决方法,希望对大家有所帮助。