编程学习网 > 编程语言 > Python > Python 脚本打包 exe,解决同事没装环境的难题!
2026
09-28

Python 脚本打包 exe,解决同事没装环境的难题!


写了个 Python 工具想发给同事用,对方说"我没装 Python"。发 .py 文件过去等于让对方走一遍装环境、装依赖的流程,大概率用不起来。用 PyInstaller 把脚本打成 .exe,对方不用装任何东西,双击就能跑。

三个场景:同事没装环境、不想暴露源码、演示时不想现场装依赖翻车。

01、安装 PyInstaller

bash

pip install pyinstaller

装完确认:pyinstaller --version,输出版本号就行。

02、最基础的打包

先写个测试脚本 hello.py:

python

print("Hello from Python!")

input("按回车退出...")

终端里执行:

bash

pyinstaller -F hello.py

打完后 exe 在 dist\hello.exe。-F 是单文件模式,所有依赖都压在一个 exe 里,发给别人只需要这一个文件。

03、常用参数

参数

作用

示例

-F

单文件 exe(便于分发)

pyinstaller -F app.py

-w

去掉控制台黑窗口(GUI 程序用)

pyinstaller -F -w app.py

--icon

自定义图标(必须是 .ico)

pyinstaller -F --icon=a.ico app.py

--name

改 exe 文件名

pyinstaller -F --name=压缩器 app.py

--add-data

附带数据文件

pyinstaller -F --add-data "config.ini;." app.py

两个容易出错的点:

-w 只适合有 GUI 界面的程序(tkinter、PyQt 等)。纯命令行脚本加了 -w,报错信息也看不见了——窗口一闪而过,你什么都不知道。

--add-data 的路径分隔符,Windows 用分号 ;,Linux/Mac 用冒号 :。这个参数经常踩坑,因为写错了不会报明确错误,打包正常但运行时找不到数据文件。

图标只接受 .ico 格式,.png 不行。在线搜"png to ico"有很多转换工具,或者用代码转:pip install pillow 然后 Image.open("a.png").save("a.ico")。

04、打包后的目录结构

CODE

项目目录/

├── hello.py        # 源码

├── dist/hello.exe  # 成品,发给别人只发这个

├── build/          # 中间产物,可删

└── hello.spec      # 打包配置文件,可保留

dist 里的 exe 就是要分发的东西。build 目录是打包过程的临时文件,随时可以删。hello.spec 是打包配置,下次可以直接 pyinstaller hello.spec 复用同样参数。

05、双击闪退怎么排查

双击 exe 黑框一闪就没——程序出错了,但窗口同时关闭。排查三步:

打开 cmd,cd 到 dist 目录,命令行跑 .\hello.exe。报错信息留在终端里,不会消失。

如果用了 -w,去掉 -w 重新打包一次,让报错可见。

代码最后加 input("按回车退出..."),窗口不会自动关。

三种最常见的闪退原因:

缺数据文件。 脚本里读了配置文件或图片,但打包时没用 --add-data 带进去。exe 运行时找不到文件就崩了。

相对路径失效。 你代码里写的 open("data.txt") 用的是相对路径。双击 exe 时的当前目录不一定是 exe 所在目录,相对路径指向了一个不存在的位置。解决办法是用 sys.executable 定位 exe 所在位置:

python

import os, sys

exe_dir = os.path.dirname(sys.executable)

data_path = os.path.join(exe_dir, "data.txt")

依赖漏打。 一些库是动态导入的,PyInstaller 分析不到。比如 pandas 依赖的某些子模块。解决方式是加 --hidden-import=模块名。

06、杀毒软件误报

MOGE NOTES · PART 06

360 和 Windows Defender 拦截 PyInstaller 打出来的 exe 是常态。打包原理是把 Python 解释器和依赖打在一起,特征(壳 + 无数字签名)和某些病毒相似。

处理方式:把 exe 所在文件夹加入杀软的排除列表。Windows Defender 的路径是"设置 → 隐私和安全 → Windows 安全中心 → 病毒和威胁防护 → 管理设置 → 排除项"。如果是在公司内部分发,让 IT 帮忙加白名单。个人用代码签名证书可以彻底解决,但一年几百到几千块,个人项目没必要。

降低误报的小技巧:--name 用正经的英文名而不是 test1、图标正常、别乱加选项——效果有限,但聊胜于无。

07、体积优化

一个 print("hello") 打出 10MB+ 的 exe 是正常的,PyInstaller 把整个 Python 解释器和所有依赖都塞进去了。

按效果排序的优化方案:

第一,用干净的虚拟环境打包。你的全局环境里装了 pandas、numpy、flask 一堆库,PyInstaller 会把它们全打进去。创建一个干净的虚拟环境只装必要的依赖,体积能小很多。

bash

python -m venv venv

venv\Scripts\activate

pip install pillow pyinstaller    # 只装需要的

pyinstaller -F app.py

deactivate

第二,不用 -F,用默认的多文件模式。-F 把所有东西压进单个 exe,运行时还要解压到临时目录,更慢更大。默认模式分发时需要整个文件夹,但更小更快。如果是在公司内部用,多文件模式反而更方便。

第三,UPX 压缩。--upx-dir 指定 UPX 路径,能再压 20%-40%。但有风险:可能被杀软更积极地拦截,个别库压完会闪退。先用原 exe 验证功能正常再加 UPX。

08、完整案例:图片批量压缩工具

python

import os

import sys

from PIL import Image

 

def compress_images(folder, quality=60, max_size=(1920, 1080)):

    """批量压缩文件夹中的图片"""

    SUPPORTED = ('.jpg', '.jpeg', '.png', '.bmp', '.webp')

 

    if not folder:

        folder = os.path.dirname(sys.executable) if getattr(sys, 'frozen', False) else os.getcwd()

 

    if not os.path.isdir(folder):

        print(f"文件夹不存在: {folder}")

        return

 

    saved = 0

    saved_bytes = 0

 

    for filename in os.listdir(folder):

        if not filename.lower().endswith(SUPPORTED):

            continue

 

        src = os.path.join(folder, filename)

        try:

            with Image.open(src) as img:

                if img.size[0] > max_size[0] or img.size[1] > max_size[1]:

                    img.thumbnail(max_size)

 

                out_dir = os.path.join(folder, 'compressed')

                os.makedirs(out_dir, exist_ok=True)

                dst = os.path.join(out_dir, filename)

 

                if img.mode in ('RGBA', 'P'):

                    img = img.convert('RGB')

                img.save(dst, 'JPEG', quality=quality)

 

                before = os.path.getsize(src)

                after = os.path.getsize(dst)

                saved += 1

                saved_bytes += (before - after)

                print(f"压缩: {filename}  {before/1024:.0f}KB -> {after/1024:.0f}KB")

        except Exception as e:

            print(f"跳过 {filename}: {e}")

 

    print(f"\n完成:共压缩 {saved} 张,节省 {saved_bytes/1024/1024:.1f} MB")

    print(f"输出目录: {os.path.join(folder, 'compressed')}")

 

if __name__ == "__main__":

    folder = sys.argv[1] if len(sys.argv) > 1 else ""

    print("图片批量压缩工具")

    compress_images(folder)

    input("按回车退出...")

注意 folder 那行——sys.frozen 判断是不是打包后的 exe 环境,是的话用 sys.executable 定位 exe 所在目录,不是的话用 os.getcwd()。这解决了双击 exe 时当前目录不确定的问题。

打包流程:

bash

python -m venv venv

venv\Scripts\activate

pip install pillow pyinstaller

pyinstaller -F --name 图片压缩器 --icon=logo.ico img_compress.py

deactivate

dist\图片压缩器.exe 就是成品。双击前先在命令行跑一次:dist\图片压缩器.exe "D:\test_imgs",确认压缩后图片正常打开、尺寸没问题,再分发给别人。

09、打包成 exe 的几个坑

双击闪退。 先用命令行跑 dist\xxx.exe,八成是缺文件或路径错误。不要一上来就觉得是 PyInstaller 的 bug。

`--add-data` 分隔符写错。 Windows 是分号 ;,Linux/Mac 是冒号 :。这个坑几乎每个新手都踩。

相对路径在 exe 里失效。 exe 运行时的当前目录不一定是 exe 所在目录。用 os.path.dirname(sys.executable) 拼路径。

`--icon` 传 .png 报错。 只接受 .ico。

pandas/matplotlib 打包困难。 依赖树复杂,打包经常失败或体积爆炸。加 --hidden-import 手动指定遗漏模块,或者考虑换轻量实现。

杀软删除 exe。 加白名单或者购买代码签名证书。

每次改代码都要重新打包。 别用旧 exe 测试新功能,也别用旧 exe 分发给别人。

分发前自己当一回纯用户。 把 exe 复制到另一台没装 Python 的电脑上跑一遍全流程,确认没问题再发出去。

以上就是“Python 脚本打包 exe,解决同事没装环境的难题”的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。  

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取