打包
安装最新版PyInstaller
pip3install--upgrade pyinstaller修改 main.py 适配打包路径
打包后程序的运行目录会变化(PyInstaller 会创建临时目录_MEIPASS),必须修改main.py中所有硬编码路径,确保能找到静态文件、配置文件等资源。
# -------------------------- PyInstaller 路径适配核心函数 --------------------------defget_resource_path(relative_path):""" 获取打包后资源的真实路径(适配PyInstaller) - 开发环境:返回项目根目录相对路径 - 打包后:返回PyInstaller临时目录(_MEIPASS)中的路径 """ifhasattr(sys,'_MEIPASS'):# 打包后运行模式base_path=Path(sys._MEIPASS)else:# 开发环境运行模式base_path=Path(os.path.abspath("."))returnstr(base_path/relative_path)创建定制化 Spec 文件
生成基础 Spec 文件:
pyinstaller -F --name video_surveillance main.py执行后会生成
video_surveillance.spec文件。替换为定制化 Spec 文件
将生成的
video_surveillance.spec内容替换为以下完整配置upx github下载 或者官网
# -*- mode: python ; coding: utf-8 -*-importosimportsys from pathlibimportPath# -------------------------- 基础配置 --------------------------# 获取当前Spec文件所在目录#current_dir = Path(__file__).parent# -------------------------- 修复__file__未定义问题 --------------------------# 兼容PyInstaller执行Spec文件时的上下文,获取当前Spec文件所在目录def get_spec_dir():if'__file__'inglobals():returnPath(__file__).parent else:# 备用方案:从命令行参数中提取Spec文件路径forarginsys.argv:ifarg.endswith('.spec')and os.path.exists(arg):returnPath(arg).parent# 最终备用:当前工作目录returnPath(os.getcwd())# 获取当前Spec文件所在目录(修复核心)current_dir=get_spec_dir()# 定义需要打包的资源(格式:(源路径, 目标路径))# 目标路径是打包后程序内部的相对路径,需和main.py中的get_resource_path对应# -------------------------- 资源列表(关键) --------------------------# 1. 静态文件:打包整个static目录(包含所有子目录和文件)static_dir=current_dir /"static"# 2. 配置文件:打包config目录config_dir=current_dir /"config"# 最终打包资源列表datas=[(str(static_dir),"static"),# 静态文件目录(完整打包)(str(config_dir),"config"),# 配置文件目录]# -------------------------- 隐藏依赖(解决动态导入问题) --------------------------hidden_imports=[# Uvicorn/FastAPI核心依赖"uvicorn.lifespan","uvicorn.lifespan.on","uvicorn.protocols.websockets.auto","uvicorn.protocols.http.auto","uvicorn.protocols.http.h11_impl","uvicorn.protocols.websockets.websockets_impl",# WebSocket依赖"websockets",# FastAPI依赖"fastapi.routing","fastapi.dependencies","fastapi.staticfiles","fastapi.responses",# 其他依赖"python_multipart","pydantic","starlette","starlette.websockets","starlette.responses",# 通用ARM64必需依赖"h11","typing_extensions",]# -------------------------- 打包配置 --------------------------block_cipher=None a=Analysis(['main.py'],# 主程序入口pathex=[str(current_dir)],# 项目根目录binaries=[],# 二进制文件(自动识别)datas=datas,# 静态资源hiddenimports=hidden_imports,# 隐藏依赖hookspath=[],hooksconfig={},runtime_hooks=[],excludes=['tkinter','matplotlib','numpy','pandas'],# 排除无用依赖减小体积win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False,)pyz=PYZ(a.pure, a.zipped_data,cipher=block_cipher)# -------------------------- 可执行文件配置 --------------------------use_upx=Falseifsys.platform=="win32"and sys.maxsize>2**32:# 仅Windows x64启用UPXuse_upx=True exe=EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas,[],name='video_surveillance',# 可执行文件名称debug=False,# 关闭调试模式 仅关闭 PyInstaller 底层的调试日志,不影响代码中的任何打印 / 日志:bootloader_ignore_signals=False,strip=False,upx=use_upx,# 压缩可执行文件(需安装UPX,可选)能 有极轻微的启动延迟(毫秒级),运行中无任何性能损失:upx_exclude=[],runtime_tmpdir=None,console=True,# 保留控制台窗口(方便查看日志)disable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,)# Windows额外配置(可选)ifsys.platform=="win32":exe=EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas,[],name='video_surveillance',debug=False,bootloader_ignore_signals=False,strip=False,upx=use_upx,upx_exclude=[],runtime_tmpdir=None,console=True,# 如需隐藏控制台,改为 windowed=Truedisable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,)执行打包
pyinstaller video_surveillance.spec重新打包
# 先清理旧的打包产物(可选,避免缓存问题)rm-rf build dist __pycache__# 重新执行打包pyinstaller video_surveillance.spec