PyInstaller打包Flask应用时,非入口脚本无法导入外部依赖包的问题求助
PyInstaller打包Flask应用时,非入口脚本无法导入外部依赖包的问题求助
我第一次用PyInstaller打包Flask应用,遇到了一个特别奇怪的问题:入口脚本run.py里能正常导入Waitress这类外部依赖,但它调用的其他脚本(比如app.py)里却找不到Flask、flask_cors这些依赖,想请教大家这是怎么回事,该怎么解决?
我的打包配置
我在项目根目录执行的打包命令是:
pyinstaller --onefile --paths .venv/Lib/site-packages --add-data "apps;apps" apps/backend/routes/run.py
原本以为这个命令会把虚拟环境site-packages里的所有依赖,以及项目内apps/目录下的代码都包含进去,但实际运行打包后的run.exe时出了问题。
项目目录结构
我的项目目录大概是这样的:
root/ |-- apps/ | |-- backend/ | | |-- routes/ | | | |-- app.py | | | |-- run.py # 入口脚本 | | |-- utils/ | |-- frontend/ |-- build/ |-- dist/ | |-- run.exe # 打包后的可执行文件 |-- run.spec
关键代码片段
入口脚本run.py核心内容
这个脚本是打包的入口,里面处理了PyInstaller打包后的路径问题,并且尝试导入后续需要的模块:
"""Entry-point file. Runs the Flask app""" import os import sys import logging import multiprocessing from waitress import serve # 这个导入在打包后能正常工作 def resource_path(relative_path:str): """ 把相对于项目根的路径转换为相对于可执行文件或PyInstaller临时目录的路径 """ try: # 生产模式:用PyInstaller临时目录 base_path = sys._MEIPASS except AttributeError: # 开发模式:用项目根目录 base_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "../../../") ) return os.path.join(base_path, relative_path) # 把apps/目录加入sys.path,方便后续导入 sys.path.insert(0, resource_path("apps")) # 导入其他模块 from apps.backend.routes.app import create_app from apps.backend.utils.shutdown_manager import ShutdownManager # ... 后续启动Flask应用的代码
被调用的app.py核心内容
这个脚本是Flask的应用工厂,被run.py导入并调用:
"""App Factory. Creates instances of a configured Flask app.""" from flask import Flask # 打包运行时这里会报ModuleNotFoundError from flask_cors import CORS import logging def create_app(config_obj:str, shutdown_manager = None)->Flask: app = Flask(__name__) return app
遇到的错误及尝试
直接运行./dist/run.exe时,会抛出如下错误:
Traceback (most recent call last): File "backend\routes\run.py", line 33, in <module> File "C:\Users\<user>\AppData\Local\Temp\_MEI274562\apps\backend\routes\app.py", line 3, in <module> from flask import Flask ModuleNotFoundError: No module named 'flask' [PYI-18800:ERROR] Failed to execute script 'run' due to unhandled exception!
我一开始很困惑——Flask明明在虚拟环境里(用pip show flask能确认),而且run.py里导入Waitress完全没问题。
后来我做了个测试:在run.py里手动添加了from flask import Flask这行代码,这时候错误变成了:
Traceback (most recent call last): File "backend\routes\run.py", line 34, in <module> File "C:\Users\<user>\AppData\Local\Temp\_MEI113522\apps\backend\routes\app.py", line 4, in <module> from flask_cors import CORS ModuleNotFoundError: No module named 'flask_cors' [PYI-10220:ERROR] Failed to execute script 'run' due to unhandled exception!
这说明问题很明确:只有入口脚本run.py里直接导入的依赖能被PyInstaller识别并打包,其他被它间接调用的脚本里的外部依赖都没被包含进去。我试了项目里其他几个需要外部依赖的脚本,都是同样的情况。
我的疑问
我已经在打包命令里指定了虚拟环境的site-packages路径,也用--add-data把apps/目录包含进去了,而且run.py里也通过sys.path处理了路径问题,为什么其他脚本还是找不到依赖呢?有没有人遇到过类似的问题,求指点怎么解决!
内容来源于stack exchange




