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

使用PyInstaller打包FastAPI应用时app.mount功能失效求助

FastAPI单文件打包后无法找到static/templates目录的解决方法

问题重现

我的FastAPI应用代码如下:

app = FastAPI()
base_dir = os.path.dirname(os.path.abspath(__file__))

static_dir = os.path.join(base_dir, "app/static")
templates_dir = os.path.join(base_dir, "app/templates")

app.mount("/static", StaticFiles(directory=static_dir), name="static")
app.mount("/templates", StaticFiles(directory=templates_dir), name="templates")

app.include_router(auths.auth)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

本地用uvicorn、python main.py或fastapi dev运行都正常,但用pyinstaller -F --onefile main.py打包成单文件后,执行exe会报错:

PS C:\Users\Nitish Kumar\abc\cas-apis\dist> .\main.exe
Database connection is active.
Traceback (most recent call last):
  File "main.py", line 84, in <module>
  File "starlette\staticfiles.py", line 59, in __init__
RuntimeError: Directory 'app/static' does not exist
[3076] Failed to execute script 'main' due to unhandled exception!

注释掉app.mount相关代码后打包可正常运行,求解决办法。

原因分析

PyInstaller单文件模式(-F/--onefile)会把所有依赖打包成一个exe,运行时自动解压到系统临时目录(比如C:\Users\XXX\AppData\Local\Temp\_MEIXXXXXX\),但app/static和app/templates目录没被包含进打包文件,解压后临时目录里找不到这些文件夹,导致StaticFiles初始化失败。

另外,打包成单文件后,os.path.abspath(__file__)指向的是临时目录里的解压脚本,不是本地源码目录,原来的路径计算逻辑也不适用。

解决方案

步骤1:修改代码适配打包后的路径

区分源码运行和exe运行环境,调整静态文件路径的获取逻辑:

import os
import sys
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()

def get_resource_path(relative_path):
    # 判断是否为打包后的exe环境
    if hasattr(sys, '_MEIPASS'):
        # 打包后资源文件会解压到sys._MEIPASS目录
        base_dir = sys._MEIPASS
    else:
        # 源码运行时用当前文件所在目录
        base_dir = os.path.dirname(os.path.abspath(__file__))
    return os.path.join(base_dir, relative_path)

# 获取正确的静态文件路径
static_dir = get_resource_path("app/static")
templates_dir = get_resource_path("app/templates")

app.mount("/static", StaticFiles(directory=static_dir), name="static")
app.mount("/templates", StaticFiles(directory=templates_dir), name="templates")

app.include_router(auths.auth)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

步骤2:让PyInstaller包含静态文件

有两种方式实现:

方式一:命令行参数直接指定

打包时添加--add-data参数,Windows用分号分隔路径,Linux/macOS用冒号:

# Windows系统
pyinstaller -F --onefile --add-data "app/static;app/static" --add-data "app/templates;app/templates" main.py

# Linux/macOS系统
pyinstaller -F --onefile --add-data "app/static:app/static" --add-data "app/templates:app/templates" main.py

方式二:修改spec文件打包

  1. 先生成spec文件:
pyinstaller -F --onefile main.py
  1. 打开main.spec,找到datas字段,添加静态文件映射:
a = Analysis(
    ['main.py'],
    # 其他参数保持不变
    datas=[('app/static', 'app/static'), ('app/templates', 'app/templates')],
    # 其他参数保持不变
)
  1. 用spec文件重新打包:
pyinstaller main.spec

验证

打包完成后运行生成的exe文件,即可正常加载静态文件,不会再出现目录不存在的错误。

内容的提问来源于stack exchange,提问作者Nitish Roy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:28:24