如何将含多子文件夹与依赖的Flask项目打包为单EXE并解决模板缺失
解决Flask项目PyInstaller单文件打包后模板找不到的问题
1. 调整Flask App的路径配置
在website/__init__.py中修改create_app函数,添加对PyInstaller单文件模式的路径适配,确保程序能找到打包后的静态文件和模板:
import os import sys from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager db = SQLAlchemy() DB_NAME = "database.db" def create_app(): app = Flask(__name__) app.config['SECRET_KEY'] = 'your-secret-key-here' # 适配PyInstaller单文件运行环境 if getattr(sys, 'frozen', False): # 打包后运行时,资源会被解压到临时目录,通过sys._MEIPASS获取路径 template_dir = os.path.join(sys._MEIPASS, 'website', 'templates') static_dir = os.path.join(sys._MEIPASS, 'website', 'static') app.template_folder = template_dir app.static_folder = static_dir # 可选:把数据库放在用户文档目录,避免权限问题 db_path = os.path.join(os.path.expanduser('~'), 'Documents', DB_NAME) app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{db_path}' else: # 开发环境下使用相对路径 app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) from .views import views from .auth import auth app.register_blueprint(views, url_prefix='/') app.register_blueprint(auth, url_prefix='/') from .models import User, Project with app.app_context(): db.create_all() login_manager = LoginManager() login_manager.login_view = 'auth.login' login_manager.init_app(app) @login_manager.user_loader def load_user(id): return User.query.get(int(id)) return app
2. 修正PyInstaller打包命令
调整资源文件的映射路径,确保打包后资源结构与代码中的路径匹配,同时修正主文件路径:
# Windows环境命令 pyinstaller --onefile ^ --add-data "website/templates;website/templates" ^ --add-data "website/static;website/static" ^ --hidden-import flask_sqlalchemy ^ --hidden-import flask_login ^ --hidden-import werkzeug.security ^ --hidden-import sqlalchemy.sql ^ --hidden-import json ^ --hidden-import base64 ^ main.py
说明:
- Linux/macOS环境下,把路径分隔符
;换成:--add-data的目标路径保留website/前缀,和代码中sys._MEIPASS/website/templates的路径对应- 主文件是根目录的
main.py,而非website/main.py
3. 错误原因解析
- 原命令主文件路径错误:指定了
website/main.py,但实际主文件在根目录,导致打包结构混乱 - 资源映射路径错误:原命令把模板放到了根目录
templates,但代码中期望从website/templates读取,导致Flask找不到模板 - 未适配单文件模式:PyInstaller单文件运行时会把资源解压到临时目录,必须通过
sys._MEIPASS获取正确路径,否则相对路径失效
内容的提问来源于stack exchange,提问作者user21955070
相关产品推荐
相关产品推荐

