You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过PyInstaller保留项目源码至_internal文件夹以支持自动更新?

PyInstaller打包后实现源码替换式自动更新的方案

问题背景

我原本的应用自动更新流程是:

  • 定期检查PyPI上的应用新版本
  • 用命令 pip download --no-deps --no-binary :all: project==X.X.X 下载源码包 project-X.X.X.tar.gz,提取后替换项目里的project/文件夹
  • 重启应用完成更新

项目结构如下:

app.py
project/
    utils.py
    core.py

但用PyInstaller打包后,所有代码都被编译进可执行文件,没法替换源码实现更新。想知道能不能把project/源码放在PyInstaller生成的目录中直接使用,而非全部编译进可执行文件?

可行方案:把指定目录保留为源码形式打包

完全可以实现,核心思路是让PyInstaller不编译project/目录,而是把它作为外部资源打包到输出目录,具体操作如下:

1. 打包时配置PyInstaller参数

直接用命令行参数指定,把project/目录复制到打包后的目录,同时排除该模块的编译:

# Windows系统
pyinstaller --onefile --add-data "project;project" --exclude-module project app.py

# Linux/macOS系统
pyinstaller --onefile --add-data "project:project" --exclude-module project app.py
  • --add-data:把本地的project/目录原样复制到可执行文件的同层级目录下,不同系统用不同分隔符
  • --exclude-module project:告诉PyInstaller不要把project模块编译进可执行文件

如果需要更灵活的配置,也可以编写PyInstaller的spec文件,在datas里添加('project', 'project'),同时在excludes里加入'project',再用pyinstaller your_app.spec打包。

2. 修改代码的导入逻辑

因为project/现在是外部目录,需要确保应用能正确找到它。在app.py开头加上这段代码:

import sys
import os

# 判断是打包后还是开发环境,获取应用根目录
if getattr(sys, 'frozen', False):
    app_dir = os.path.dirname(sys.executable)
else:
    app_dir = os.path.dirname(os.path.abspath(__file__))

# 把project目录添加到Python的搜索路径里
sys.path.insert(0, os.path.join(app_dir, 'project'))

# 之后正常导入模块就行
from project.utils import *
from project.core import *

3. 沿用原有更新流程

打包完成后,project/会和可执行文件在同一个目录下,你原来的更新流程完全可以直接用:

  • 下载最新的project-X.X.X.tar.gz并解压出project/目录
  • 替换掉可执行文件同层级的project/文件夹
  • 重启应用就能加载新版本的代码

注意点

  • 要保证PyPI上的包包含完整的project/源码目录,结构和本地一致
  • 不同系统的--add-data分隔符要注意,别搞混了
  • 如果你的project/里有依赖其他库,要确保打包时已经把这些依赖编译进可执行文件,或者更新时同步处理

内容的提问来源于stack exchange,提问作者arthur.sw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:04:59