零代码应用开发·第 14 章·3 学时

打包成软件

把代码、解释器与全部依赖装进一个文件。自己机器上能跑,不算数。

本章精髓 程序从来不是独自在跑。它依赖解释器、依赖库、依赖这台机器上的环境。打包就是把这些行李全装进一个盒子,让拿到它的人不必安装任何东西。这是"我写了一个脚本"与"我做了一个软件"之间的分界。

学完本章后,你应该能够:

  1. 说清打包做了什么,解释一个几十行的脚本为什么会打出十几兆的文件;
  2. 用打包工具把脚本打成单文件,并说明常用参数各自的作用与代价;
  3. 说清打包之后程序位置的变化,写出打包前后都能找到数据文件的代码;
  4. 为交付物写一份 README,说明用途、用法、数据位置与已知问题;
  5. 在一台没有安装过 Python 的计算机上,从双击开始验证自己的成品。
配套演示文件 第14章演示_四个位置.html 第14章演示_他机验收.html 第14章演示_路径对照.py 第14章演示_登记器.py 第14章演示_README样例.txt

一个 exe,三样交付物

成品 · 装了什么进去 · 把风险写成问句

先看打包把什么装了进去,再看交付时到底要给几样东西。

1.1本章成品:一个双击就能用的程序

手上有一个借还登记工具,在自己电脑上跑得好好的。本章把它变成一个文件,拷进 U 盘,插到一台从来没装过 Python 的电脑上,双击就能用。

命令提示符 · 打包
…\第14章> pyinstaller --onefile --noconsole -n 借还登记器 登记器.py (中间省略数十行编译过程) Building EXE from EXE-00.toc completed successfully. 生成的文件在 dist 文件夹里

一行命令,若干分钟,得到一个十几兆的文件

1.2打包把什么装了进去

那个文件之所以能在没装过 Python 的电脑上运行,是因为它把运行所需的一切都带上了:

你写的代码
几十行
几千字节
+
解释器
python
负责执行这些代码
+
用到的库
界面、数据库…
一个都不能少
一个可执行文件
借还登记器.exe
对方不必安装任何东西

体积主要来自解释器与库,与你写了多少行几乎无关

1.3交付的不只是那个 exe

把一个 exe 单独发过去,对方多半用不起来。一份能被别人接着用下去的交付物有三样东西,缺一样都会在别人手里卡住。

第一样
可执行文件
双击就能运行,不依赖对方装过什么。这是三样里最容易做到的一样。
连中间产物一起打包发过去
第二样
数据文件
程序和数据是两回事。只发 exe,对方打开是一个空壳。备份时要备份的也是这一样。
把数据文件打进 exe 里
第三样
一份 README
写清怎么用、数据在哪、可能遇到什么问题。没有它,对方的第一句话一定是"这个怎么用"。
靠微信上补一句说明

打开 第14章演示_他机验收.html,把三样东西任意漏掉一样,看接收方在哪一步卡住。那台验收机上没有你,也没有你的解释。

讨论把三样东西都发给对方之后,他仍然可能用不起来。你能想到哪几种情况?其中哪些是可以靠 README 提前说明解决的,哪些必须改程序才行?

1.4本章新技巧:把环境说全,把已知风险写成问句

问"怎么把 Python 打包成 exe",得到的是一段通用回答。通用回答的问题在于:打包的结果高度依赖你这台机器上的具体情况,系统版本、Python 版本、打包工具版本、用到了哪些库,任何一项不同,命令和坑都可能不一样。信息不全时,对方只能按最常见的情形作答,于是要来回三四轮才对得上。

所以提问时把环境一次性说全:系统、Python 版本、用到的库、要达到的效果。更进一步的做法是点名把已知的坑问出来,例如打包之后数据文件的位置会不会变。这类问题它通常不会主动提,问了才答。

它不主动提的坑,往往不是它不知道,而是你没问到。把已知的风险点写成问句,比等它想起来可靠得多。

1.5可直接复制的提示词

发给 AI主提示词 · 打包命令与路径写法
我要把一个 Python 脚本打包成 Windows 上的单个 exe。 环境:Windows 11,Python 3.12,脚本用到 tkinter 和 sqlite3,没有其他第三方库。 要求:打包成单文件、双击时不出现黑色控制台窗口、换成我提供的 icon.ico。 另外有一个问题请一并回答: 程序运行时要读写同目录下的 items.db。打包之后,这个"同目录"会不会变? 如果会变,代码里该怎么写,才能在直接运行 .py 和运行 exe 两种情况下都找得到? 请给出完整的打包命令,并逐个参数说明是做什么用的。 路径那段代码请单独给出,并说明要替换掉原来的哪一行。
发给 AI打包报错 · 原文整段贴回去
上面的打包命令跑完报错了,完整输出如下(一个字没改): [粘贴完整输出] 我的环境:Windows 11,Python 3.12,PyInstaller 版本 [填上 pyinstaller --version 的结果]。 请先用中文解释这段错误是什么意思,再给出解决办法。 如果需要改代码,只指出改哪一行、改成什么,不要重写整个脚本。 如果需要换命令,请说明新命令与原来那条的区别在哪里。
发给 AI写 README · 给拿到成品的人看
请为下面这个程序写一份 README.txt,读者是完全不懂技术的同学。 程序功能:[一两句话说明你的程序是做什么的] 交付内容:一个 exe,一个数据文件,本说明。 已知问题:部分杀毒软件会拦截,需要手动加入信任列表。 README 要包含五部分:这是什么、怎么用、运行环境、数据存在哪里、可能遇到的情况。 用中文,不要出现"依赖""部署""环境变量"这类术语, 凡是需要读者动手的地方,写清点哪里、看到什么算成功。 不要写安装 Python 的步骤,这个程序不需要。

主提示词里的几条要求,分别对应后面要讲的知识点:

写明系统、Python 版本、用到哪些库
知识点 01、04:打包对环境敏感,信息不全时它只能按最常见的情形作答
打包之后"同目录"会不会变,代码该怎么写
知识点 05:这是本章最不容易发现的坑,它通常不会主动提
双击时不出现黑色控制台窗口
知识点 06:加之前先确认程序已经能用弹窗提示错误
逐个参数说明是做什么用的
知识点 04:参数在不同版本上写法有出入,看懂了才能自己调
报错时附上 pyinstaller --version 的结果
知识点 04:同一段报错在不同版本上原因可能完全不同
README 里不要出现依赖、部署这类术语
知识点 08:读者是拿到成品的人,不是写程序的人

1.6大模型的常见偏差

给出的参数在你装的版本上不适用。 打包工具的参数改过几轮,它给的可能是另一个版本的写法。命令报错说"无法识别的参数"时,多半就是这个原因。把版本号一并告诉它,能省掉一轮来回。

不主动提路径会变这件事。 这是本章最需要防的一种。它给的代码在直接运行时完全正常,打包之后数据悄悄写进了临时目录。这个问题必须在提示词里点名问出来,否则它多半不会提。

建议安装一堆用不上的东西。 它有时会推荐额外的打包工具、虚拟环境管理器、图标转换软件。这些在正式项目里各有用处,本章一律不需要。装得越多,出问题的地方越多。

把数据文件也打进 exe 里。 它可能建议用参数把 items.db 一起打包进去。这样做之后数据变成只读的,登记的记录下次打开就没了。数据文件要放在 exe 旁边,不要打进去。

备用方案 打包环节受网络或环境限制无法进行时,两个网页演示件可以把本章最要紧的两件事讲完:第14章演示_四个位置.html 把打包前后的四个位置并排摆出来,还能点着看数据文件落到哪里;第14章演示_他机验收.html 把验收机上的整个过程走一遍。第14章演示_登记器.py 已经写好正确的路径定位,可以直接用于对照阅读。

依赖、打包与体积 本章重点

依赖 · 环境 · 打包 · 参数

本章的核心内容集中在这一部分和下一部分。

本章要学的术语 · 八个
01依赖与环境dependency
02打包bundling
03可执行文件与体积executable
04打包工具与参数PyInstaller
05临时解压目录temp / _MEIPASS
06控制台窗口console
07误报与代码签名false positive
08版本号与发布version / release

这八个术语会原样出现在打包工具的文档、杀毒提示与开源项目的目录里。前四个在本部分讲解,后四个在第三部分讲解。

2.1四个知识点,一个一个看

01依赖与环境:它到底带着多少行李
你的代码
几十行,几千字节
界面库、数据库接口、数据处理库
解释器与系统环境
Python 本身,以及它依赖的系统组件

上面一层要跑起来,下面两层缺一样都不行

现象:同一份 .py,在你机器上跑得好好的,拷到同学那儿提示找不到模块,或者干脆双击没反应。

概念:一个程序运行时用到的、但不是它自己写的那些东西,统称依赖(dependency);这些依赖加上系统本身的状况,合称环境依赖是隐形的,你在自己机器上感觉不到它们,因为它们早就装好了。换一台机器,隐形的那部分才会现形。

类比:在家做菜不觉得自己带了多少东西,出门野炊才发现锅、火、盐一样都不能少。

02打包:把运行环境一起装进去
PY
对方要先装
Python 才能跑
EXE
对方什么都
不用装

差别不在代码,在于运行所需的东西带没带上

现象:把 exe 拷到一台没装过 Python 的电脑上,双击就能用。

概念:打包(bundling)是把你的代码、Python 解释器本身、以及用到的全部库,一起装进一个可执行文件。使用者的电脑上不需要有 Python,因为解释器就在这个文件里面。代价有两项:文件体积明显变大,以及打包过程本身对环境相当敏感,同样的命令在不同版本上结果可能不同。

类比:出门自带厨师和整套厨具,到哪儿都能开火,行李当然也就重。

03体积:几十行代码为什么打出十几兆
程序
打包后
只在终端跑的小脚本
约 7 MB
带窗口界面的登记器
约 13 MB

某台机器上的实测值,换个系统或版本还会变

现象:一个几十行的脚本,打包出来十几兆。

概念:体积几乎与你写了多少行无关,取决于打包时把哪些东西装了进去。解释器本身就有若干兆,界面库、数据处理库各自还要占一块。用不到的库不要 import,是唯一有效的减小体积的办法。至于打出来到底多大,与系统、Python 版本、库的版本都有关系,不必追求某个具体数字,只要知道它由什么决定。

类比:行李箱的重量主要来自厨具,不是来自那张菜谱。

04打包工具与参数:一行命令,四个常用参数
参数
作用
--onefile
打成单个文件
--noconsole
不弹黑窗口
--icon
指定图标
-n
指定输出名

常用的就这四个,写法在不同版本上略有出入

现象:打包用的是一行命令,后面跟着几个以减号开头的参数。

概念:PyInstaller 是最常用的打包工具,用 pip 安装。它先分析你的代码用到了哪些库,再把这些库连同解释器一起收进去。参数的写法在不同版本上并不完全一致,从网上或大模型那里拿到命令之后,先用 pyinstaller --version 看一眼自己装的是哪个版本。

类比:打包行李时选箱型:要不要合并成一件、要不要贴自己的标签。

2.2打包命令:一行命令与四个参数

先用 pip 装上工具,再在脚本所在的文件夹里执行:

pip install pyinstaller
安装打包工具。装一次即可,之后打包任何脚本都能用。
pyinstaller --version
看一眼版本号。参数写法在不同版本上略有出入,出问题时这个数字要一并告诉大模型。
pyinstaller --onefile -n 借还登记器 登记器.py
第一次打包,先不加隐藏控制台的参数。--onefile 打成单个文件,-n 指定输出的文件名。
pyinstaller --onefile --noconsole --icon=icon.ico -n 借还登记器 登记器.py
确认一切正常之后再打这一次。图标必须是真正的 .ico 格式,直接把 png 改扩展名不行。

命令跑完之后会多出三样东西:dist 文件夹里是成品,build 文件夹与那个 .spec 文件是打包过程的中间产物,交付时不必给。

两段式打包。 第一次打包不要加 --noconsole,留着黑窗口,出了错还能看见报错;确认一切正常之后再加上它重打一次。这两次的先后顺序不能颠倒,先加参数再调试,等于把唯一的线索先关掉了。

打包之后,程序换了位置 本章重点

临时目录 · 控制台 · 误报 · 版本号

这一部分是本章唯一需要改代码的地方,也是最容易被忽略的一处。

3.1另外四个知识点

05临时解压目录:数据写进去了,却留不住
同一份代码 · 连跑两次实测
第一次:/tmp/_MEI00000745dB0583/data.txt 第二次:/tmp/_MEI00000747bqcu0I/data.txt 可执行文件旁边:什么都没有

每次运行解压到不同目录,写进去的数据留不住

现象:直接运行时数据存在脚本旁边;打包之后同样的代码把数据写进了一个临时目录,而且每次运行的目录还不一样。

概念:单文件模式的程序运行时会先把自己解压到一个临时目录__file__ 指向的是那里,程序结束后该目录随即被清理。要让数据文件留在可执行文件旁边,必须改用 sys.executable 来定位。这是本章最不容易发现的一处:程序不报错,数据却存不住。

类比:搬了家还按老地址寄东西。快递没有退回,只是送到了一个临时收件点,隔天就撤了。

06控制台窗口:藏起来之后,报错也一起没了
不加参数有黑窗口报错看得见
--noconsole没有黑窗口报错也没了
先加弹窗提示两头都顾上

先把错误接住,再动手隐藏控制台

现象:加上隐藏控制台的参数之后,程序出错时窗口连闪都不闪一下,什么都看不到。

概念:--noconsole 让双击时不弹出黑色控制台窗口,有界面的程序应当加。代价是原本打印在控制台里的报错也一并消失,程序出问题时使用者只看到窗口凭空关掉。因此加这个参数的前提是:程序里已经把可能出错的地方接住,并改用弹窗提示。

类比:把后台的对讲机关掉之前,前台得先有人应声,否则出了事外面一点动静都没有。

07误报:被杀毒软件拦下不等于程序有问题
安全警告
此文件来源不明,
可能会损害你的设备。
删除仍要保留

拦的是"不认识",不是"有问题"

现象:打包好的文件被杀毒软件拦下,提示未知程序或可疑行为。

概念:打包出来的程序运行时会把自己解压到临时目录再执行,这种行为与部分恶意软件相似;加上文件没有代码签名(一份由第三方机构颁发、用于证明程序来源的凭证),因此常被误报。处理办法是把它加入信任列表,并预先写进 README。交给不熟悉的人时,这一条要写在最前面,否则对方大概率会直接删掉。

类比:新面孔进小区被门卫拦下。不是他做错了什么,是门卫不认识他。

08版本号与发布:对方手上是哪一版
最终版、最终版2 人能读,程序读不懂哪个更新说不清
v1.0、v1.1 窗口标题与 README 写同一个号一问就对得上

版本号解决的是"你手上那份是哪一版"

现象:同一份程序发出去两次,对方报告一个问题,你不知道他用的是哪一版。

概念:版本号是给这一次发布出去的东西编个号,写在窗口标题、README 与文件名上,三处一致。发布指把这一版正式交出去,此后不再私自改动。对方报告问题时,你首先要确认的往往不是问题本身,而是他用的是不是最新版,版本号看上去只是一个数字,它解决的正是这件事。

类比:教材的第几版第几次印刷。不写清楚,两个人对着不同的书讨论同一页。

本章方法 打包完必须在一台没有装过 Python 的计算机上验一次。自己机器上能跑,不算数。

3.2四个位置,打包前后对照

下面这份脚本把程序运行时的四个位置全部打印出来,直接运行一次、打包之后再运行一次,差别一目了然。这是本章最值得亲手跑一遍的一个脚本。

第14章演示_路径对照.py节选 · 可直接运行
# ① 是不是打包过的程序。打包之后 sys.frozen 才存在
frozen = getattr(sys, 'frozen', False)

# ② 源文件所在目录。打包之后指向临时解压目录,不是 exe 所在的地方
print('__file__ 所在目录 :', Path(__file__).parent)

# ③ 可执行文件所在目录。打包之后就是 exe 所在的那个文件夹
print('sys.executable 目录:', Path(sys.executable).parent)

# ④ 当前工作目录。取决于使用者从哪里启动,与程序放在哪里无关
print('当前工作目录   :', os.getcwd())

# ⑤ 打包时临时解压到哪里。只有打包后的单文件模式才有这一项
if hasattr(sys, '_MEIPASS'):
    print('临时解压目录   :', sys._MEIPASS)

# ⑥ 本章要记住的写法:数据文件放在程序旁边时,用这个函数定位
def app_dir():
    if getattr(sys, 'frozen', False):
        return Path(sys.executable).parent
    return Path(__file__).parent

把它打包一次,两次运行的结果对照如下。这是在同一台机器上实际跑出来的:

位置直接运行 .py打包成单文件之后
__file__ 所在目录脚本所在的文件夹临时解压目录,每次运行都不同
sys.executable 目录Python 解释器所在目录exe 所在的文件夹
当前工作目录启动命令时所在的位置使用者从哪里启动就是哪里
sys._MEIPASS不存在临时解压目录
三项都会变,只有 sys.executable 指向的位置是你想要的那个
用错位置时,程序不报错,数据却存不住。 实测把一段写文件的代码打包之后连跑两次,第一次写进了 /tmp/_MEI00000745dB0583,第二次写进了 /tmp/_MEI00000747bqcu0I两次是不同的目录,而可执行文件旁边始终什么都没有。程序每次都提示写入成功,使用者却发现上次登记的记录不见了。这类问题在自己机器上直接运行 .py 时永远不会出现,只有打包之后才暴露。

打开 第14章演示_四个位置.html,切换"直接运行"与"打包后",再点几次"写一条记录",看数据落在哪里、下次还在不在。

getattr(sys, 'frozen', False)
判断当前是不是打包过的程序。打包之后这一项才存在,直接运行 .py 时取不到,所以第三个参数给了默认值 False。 写成 sys.frozen 时,直接运行 .py 会因为取不到这一项而报错
Path(sys.executable).parent
可执行文件所在的文件夹。打包之后它就是 exe 那个文件夹,与使用者从哪里启动无关。 直接运行 .py 时它指向 Python 解释器的安装目录,所以不能一律用它
os.getcwd()
当前工作目录。使用者双击、还是从别的文件夹启动,这个值就不一样。 用它定位数据文件时,换一种启动方式就找不到库了
def app_dir(): …
把两种情况合成一个函数。此后凡是要定位数据文件的地方一律调用它,打包前后都对。 不写这个函数、在各处分别判断时,改一次要改好几处,漏掉一处就出问题
讨论为什么"在自己机器上能跑"不能作为验收标准?除了没装 Python 之外,另一台电脑还可能在哪些方面与你的不同?想一想系统版本、用户名里的中文、磁盘权限这几项。

完整演示与一条行业惯例

改路径 · 打包 · 换机验证

从一个只在自己机器上能跑的脚本,到一份别人拿到就能用的交付物。

4.1演示步骤

1
确认脚本在本机能完整跑通
功能没跑通就打包,出了问题分不清是代码的事还是打包的事
产出:一个可用的脚本
2
先跑一次路径对照脚本,看清四个位置
记下直接运行时的四个值,一会儿打包之后再跑一次做对照。这一步花两分钟,能省掉后面一小时的排查
产出:一组基准数值
3
改掉定位数据文件的那几行
Path(__file__) 换成 app_dir()。改完先直接运行一次,确认功能没被改坏
产出:打包前后都能定位的代码
4
第一次打包,不加隐藏控制台的参数
留着黑窗口,出了错还能看见报错。打包过程要跑一两分钟,属正常。成品在 dist 文件夹里
产出:第一版可执行文件
5
双击运行,重点看数据文件落在哪里
操作一次,然后看 exe 旁边有没有出现数据文件。没出现,就是第 3 步没改对,回去重改。把打包后的路径对照结果与第 2 步的基准比一比
产出:数据落位正确的验证
6
加上隐藏控制台与图标,重打一次
加参数之前先确认程序里的错误都已用弹窗接住,否则出问题时使用者什么都看不到
产出:正式版可执行文件
7
拷进 U 盘,到验收机上双击验证
验收机是一台没有装过 Python 的电脑。把可执行文件、数据文件、README 三样一起拷过去,从双击开始完整走一遍。这一步通过,本章才算完成
产出:在他机运行成功的截图

4.2前沿三分钟:把环境一起交付这件事

每章固定栏目 · 一条与本章内容相关的行业动态

"在我这儿能跑"是软件行业流传多年的一句话,指的正是本章这个问题:程序在开发者机器上正常,换一台就出状况,原因往往不在代码,而在两台机器的环境不同。行业为此发展出的解决思路始终是同一个方向,把程序运行所需的环境连同程序一起交付出去,让接收方不必自己配。

本章用的打包工具是这个思路在桌面程序上的做法。服务器端更常见的是容器技术,它把操作系统层面的依赖也一并封进一个镜像,接收方只要能运行容器就能跑起来。两者的做法不同,出发点完全一致:不要求对方复现你的环境,而是把环境带过去。

代价也是同一个:体积。带上整套环境之后,一个几十行的程序动辄十几兆,容器镜像上百兆更是常事。这笔交换在今天几乎总是划算的,因为磁盘比人的时间便宜得多,配环境这件事花掉的时间才是真正的成本。

讨论把整套运行环境打进交付物,代价是体积。如果这个程序要发给一百个人,每人下载十几兆,这笔账还划得来吗?换成让每个人自己装 Python 再运行脚本,两种做法的总成本各由谁承担?

上机实验 作业 4

三选一 · 六步 · 换台电脑验

上机环节由此开始,本次上机的成果就是作业 4,当堂完成并提交。

5.1三个题目,任选其一

题目 A
借还登记器

把一个带数据库的登记工具打包成可执行文件。

通用
题目 B
资料整理器

把一个批量处理文件的工具打包,供不会用终端的人使用。

偏文科
题目 C
数据汇总器

把一个多表合并统计的工具打包,交给需要出报表的人。

偏理工

三个题目都要求成品能在一台没有装过 Python 的计算机上独立运行,并且要读写自己的数据文件。手上没有合适作品的,可以直接用演示件里的登记器作为起点。允许更换题材。

5.2上机六步

1
选定要打包的脚本,确认功能完整可用
先在本机跑一遍,把功能问题解决干净。带界面的作品,确认出错时是弹窗提示而不是黑窗口报错
产出:一个可用的脚本
2
改掉数据文件的定位方式,先直接运行验证
改成 app_dir()。改完先按 .py 运行一次,确认数据仍然存在原来的位置
产出:改过路径的脚本
3
打包,并在自己机器上完整操作一遍
重点确认数据文件出现在可执行文件旁边,而不是别处。这一条不过,后面都不用做了
产出:一个可执行文件与运行截图
4
写 README,五部分齐全
写完自己按着读一遍,凡是自己都答不上来的地方,回去改程序或改说明
产出:一份 README
5
到验收机上验证,全程不作口头说明
把三样东西拷过去,双击开始。只能照 README 操作,卡在哪一步就说明 README 缺了什么
产出:他机运行截图
6
组内互测:交给同组同学,只给三样东西
不要在旁边指导。他卡在哪一步、哪句说明看不懂,如实记下来,并写清你踩到并解决的那个打包问题
产出:互测记录与一句问题说明

5.3共同验收标准

在没装过 Python 的计算机上独立运行 对方不必安装任何东西 在验收机上双击运行,完成一次完整操作
数据文件出现在可执行文件旁边 不是临时目录,不是别处 操作一次后,看可执行文件所在文件夹里有没有数据文件
关掉重开,数据还在 上次登记的内容能读出来 操作一次,关闭程序,重新打开查看
出错时有中文提示 不是窗口凭空关掉 手工制造一次错误,例如把数据文件设为只读
README 五部分齐全 这是什么、怎么用、运行环境、数据在哪、可能遇到什么 照 README 操作一遍,看能不能独立完成
交付物三样齐整 可执行文件、数据文件、说明文件 打开压缩包,三样都在,没有多余的中间产物
写清踩到并解决的那个问题 具体到现象与做法 文档里有一段文字,写明遇到了什么、怎么解决的

5.4常见错误与处理

pyinstaller 不是内部或外部命令
工具没装,或者装到了另一个 Python 环境
运行 pip install pyinstaller;仍不行时改用 python -m PyInstaller
提示无法识别的参数
参数写法与本机的工具版本对不上
运行 pyinstaller --version,把版本号连同报错一起发给大模型
双击后闪一下就没了
程序运行出错,控制台随即关闭
在终端里运行这个可执行文件,报错就留在屏幕上了;或者先去掉隐藏控制台的参数重打一次
程序能开,但数据每次都不见了
数据写进了临时解压目录
改用 app_dir() 定位数据文件,重新打包
杀毒软件直接把成品删了
打包出来的程序没有代码签名,被误报
在杀毒软件中加入信任列表,并把这一条写进 README
--icon 报错说图标无效
用了 png 直接改扩展名,不是真正的 ico
用图标转换工具生成正规的 .ico 文件再指定
打包过程中提示找不到某个模块
工具没有分析出这个库被用到了
把完整输出发给大模型,通常用 --hidden-import 显式指定即可
在别人电脑上提示没有权限
程序被放在了只读位置,无法在旁边写数据
改放到桌面或文档目录;README 里要提前写明这一条

5.5提交内容

交付包
可执行文件、数据文件、README,三样放在一个文件夹里
压缩成一个包
源码
打包所用的 .py,以及那条打包命令
.py 文件加一行命令
他机运行截图
在没装过 Python 的计算机上运行的画面
一张截图或一段录屏
问题说明
你踩到并解决的那个打包问题
一段文字

提交方式:按教师提供的作业模板填写,文档开头注明所选题目。提交渠道见课堂通知,当堂提交。

作业 4 评分构成占比
能在他机独立运行
40%
功能完整可用
35%
交付物齐整
25%

5.6再进一步(选做)

把版本号写进程序:在窗口标题或界面上显示一个版本号,README 里也写同一个号,每改一次就往上加一位。

做完会碰到一个需要判断的问题:同一份程序发出去两次之后,你未必说得清对方手上是哪一版。对方报告一个问题时,你首先要确认的往往不是问题本身,而是他用的是不是最新版。版本号看上去只是一个数字,它解决的是这件事。

本章小结

本章五条结论

  1. 程序从来不是独自在跑。打包就是把代码、解释器与全部依赖装进一个文件,体积主要来自后两样。
  2. 打包之后程序的位置变了。定位数据文件要用可执行文件所在目录,用错时程序不报错,数据却存不住。
  3. 两段式打包:先留黑窗口调通,再加隐藏参数重打。顺序颠倒,等于把唯一的线索先关掉。
  4. 交付物是三样:可执行文件、数据文件、说明文件。少一样,对方就会卡在某一步,而且多半不会来问。
  5. 自己机器上能跑不算数。必须在一台没有装过 Python 的计算机上,从双击开始完整走一遍。
本章脉络