You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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-dataapps/目录包含进去了,而且run.py里也通过sys.path处理了路径问题,为什么其他脚本还是找不到依赖呢?有没有人遇到过类似的问题,求指点怎么解决!

内容来源于stack exchange

火山引擎 最新活动