文章目录
-
- from flask import Flask import os def create_app(env: str = None): “”” 应用工厂函数(支持指定环境:dev/prod/win) :param env: 环境标识(dev=开发/Windows, prod=生产/Linux) “”” app = Flask(__name__) # 加载配置(根据环境自动切换) env = env or os.getenv(“FLASK_ENV”, “dev”) if env == “dev” or env == “win”: app.config.from_object(“app.config.win”) elif env == “prod”: app.config.from_object(“app.config.prod”) else: app.config.from_object(“app.config.base”) # 注册多蓝图(拆分的接口模块) from app.api.user import user_bp from app.api.order import order_bp app.register_blueprint(user_bp, url_prefix=”/api/user”) app.register_blueprint(order_bp, url_prefix=”/api/order”) return app
- from flask import Blueprint, jsonify, request from app.utils.common import encrypt_password # 导入工具类(多py文件调用) user_bp = Blueprint(“user”, __name__) # 用户登录接口 @user_bp.post(“/login”) def login(): data = request.get_json() username = data.get(“username”) password = encrypt_password(data.get(“password”)) # 调用工具类 return jsonify({ “code”: 200, “msg”: “登录成功”, “data”: {“username”: username, “token”: f”token_{username}”} }) # 用户信息接口 @user_bp.get(“/info”) def get_user_info(): user_id = request.args.get(“id”) return jsonify({ “code”: 200, “data”: {“id”: user_id, “name”: “张三”, “age”: 25} })
- from flask import Blueprint, jsonify from app.utils.db import get_order_data # 导入数据库工具类 order_bp = Blueprint(“order”, __name__) # 订单列表接口 @order_bp.get(“/list”) def get_order_list(): orders = get_order_data() # 调用工具类 return jsonify({ “code”: 200, “data”: orders })
- import hashlib def encrypt_password(password: str) -> str: “””密码加密工具””” return hashlib.md5((password + “salt123”).encode()).hexdigest() def check_params(params: dict, required: list) -> bool: “””参数校验工具””” return all([p in params for p in required])
- def get_order_data(): “””模拟数据库查询订单数据””” return [ {“order_id”: “1001”, “amount”: 99.9, “status”: “paid”}, {“order_id”: “1002”, “amount”: 199.9, “status”: “unpaid”} ]
- DEBUG = True # Windows 开发环境开启DEBUG HOST = “127.0.0.1” # Windows 本地访问 PORT = 5000 SECRET_KEY = “win-secret-key-123” # Windows 特有配置(如本地数据库路径) DB_PATH = “C:/flask-api/data.db”
- DEBUG = False # 生产环境关闭DEBUG HOST = “0.0.0.0” # 允许外部访问 PORT = 5000 SECRET_KEY = “prod-secret-key-456” # Linux 特有配置(如服务器数据库地址) DB_PATH = “/opt/flask-api/data.db”
- import sys from app import create_app if __name__ == “__main__”: # 识别运行环境(Windows/Linux) env = “win” if sys.platform == “win32” else “prod” # 手动指定环境:python run.py prod if len(sys.argv) > 1: env = sys.argv[1] app = create_app(env=env) app.run( host=app.config[“HOST”], port=app.config[“PORT”], debug=app.config[“DEBUG”] )
- # 核心依赖(跨平台兼容) Flask==2.3.3 gunicorn==21.2.0 # Linux/Docker用(Windows可选) waitress==2.1.2 # Windows替代Gunicorn的WSGI服务器 requests==2.31.0 pywin32>=306 # Windows 进程守护(可选) supervisor==4.2.5 # Linux 进程守护(Windows也可装)
- 安装 Python 3.8+(勾选 “Add Python to PATH”); 验证环境: python –version # 或 python3 –version pip –version 解压 / 克隆项目到本地(如 D:flask-multi-api)。
- # 进入项目目录 cd D:flask-multi-api # 创建虚拟环境 python -m venv venv # 激活虚拟环境(Windows 命令行) venvScriptsactivate.bat # 如果是PowerShell,执行: # venvScriptsActivate.ps1 # 安装依赖 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
- # 方式1:直接启动(自动识别Windows环境) python run.py # 方式2:手动指定win环境 python run.py win 测试接口(浏览器 / Postman/curl): # 测试用户接口 curl “http://127.0.0.1:5000/api/user/info?id=1” # 测试订单接口 curl “http://127.0.0.1:5000/api/order/list”
- Flask 内置服务器不适合生产,Windows 用 waitress 替代 Gunicorn,结合 Supervisor 或 NSSM 实现后台运行。
- 安装 Supervisor(Windows 版): pip install supervisor 创建 supervisord.conf 配置文件(项目根目录): [unix_http_server] file = NUL # Windows 无需unix socket [inet_http_server] port = 127.0.0.1:9001 # Supervisor 管理端口 username = admin password = 123456 [supervisord] logfile = D:flask-multi-apilogssupervisord.log logfile_maxbytes = 50MB logfile_backups = 10 loglevel = info pidfile = D:flask-multi-apisupervisord.pid nodaemon = false # 后台运行 minfds = 1024 minprocs = 200 environment = FLASK_ENV=”win” [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurl = http://127.0.0.1:9001 # Flask 应用配置 [program:flask-api] directory = D:flask-multi-api command = D:flask-multi-apivenvScriptswaitress-serve.exe –host=0.0.0.0 –port=5000 run:create_app(‘win’) autostart = true autorestart = true startretries = 3 stdout_logfile = D:flask-multi-apilogsflask-api.log stdout_logfile_maxbytes = 50MB stdout_logfile_backups = 10 redirect_stderr = true 创建日志目录: mkdir D:flask-multi-apilogs 启动 Supervisor: # 生成默认配置(可选) echo_supervisord_conf > supervisord.conf # 启动Supervisor supervisord -c supervisord.conf # 管理命令 supervisorctl -c supervisord.conf status # 查看状态 supervisorctl -c supervisord.conf start flask-api # 启动应用 supervisorctl -c supervisord.conf restart flask-api # 重启
- 下载 NSSM,解压到 D:nssm; 注册为 Windows 服务: # 进入NSSM目录 cd D:nssmwin64 # 注册服务(名称:FlaskAPI) nssm install FlaskAPI D:flask-multi-apivenvScriptspython.exe # 设置服务参数 nssm set FlaskAPI AppParameters “run.py win” nssm set FlaskAPI AppDirectory D:flask-multi-api nssm set FlaskAPI Start SERVICE_AUTO_START # 开机自启 nssm set FlaskAPI AppStdout D:flask-multi-apilogsstdout.log nssm set FlaskAPI AppStderr D:flask-multi-apilogsstderr.log 启动 / 管理服务: nssm start FlaskAPI # 启动 nssm stop FlaskAPI # 停止 nssm restart FlaskAPI # 重启 nssm remove FlaskAPI confirm # 卸载
- # 查看5000端口占用 netstat -ano | findstr :5000 # 杀死占用进程(PID替换为实际值) taskkill /F /PID 1234
- # 创建目录 mkdir -p /opt/flask-multi-api # 上传项目(用scp/rz/git) scp -r D:flask-multi-api root@<LinuxIP>:/opt/ cd /opt/flask-multi-api
- python3 -m venv venv source venv/bin/activate pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
- # 直接启动(自动识别Linux环境) gunicorn -w 4 -b 0.0.0.0:5000 “run:create_app(‘prod’)”
- 修改 /etc/supervisord.d/flask-api.ini: [program:flask-api] directory=/opt/flask-multi-api command=/opt/flask-multi-api/venv/bin/gunicorn -w 4 -b 0.0.0.0:5000 “run:create_app(‘prod’)” autostart=true autorestart=true user=root stdout_logfile=/var/log/flask-api.log 重启 Supervisor: supervisorctl reload supervisorctl start flask-api
- # 基础镜像(跨平台兼容) FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 环境变量(生产环境) ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV FLASK_ENV=prod # 安装系统依赖 RUN apt update && apt install -y –no-install-recommends gcc && rm -rf /var/lib/apt/lists/* # 复制依赖清单 COPY requirements.txt . RUN pip install –no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 复制所有多文件代码(关键:保留目录结构) COPY . . # 暴露端口 EXPOSE 5000 # 启动命令(多文件入口) CMD [“gunicorn”, “-w”, “4”, “-b”, “0.0.0.0:5000”, “run:create_app(‘prod’)”]
- 安装 Docker Desktop(Windows),开启 WSL2 后端; 进入项目目录,构建镜像: docker build -t flask-multi-api:v1 .
- # Windows/Linux 通用命令 docker run -d –name flask-multi-api -p 5000:5000 –restart=always -v /var/log/flask-api:/app/logs # 挂载日志(Linux) # Windows 挂载日志:-v D:flask-multi-apilogs:/app/logs flask-multi-api:v1
- 编写 docker-compose.yml: version: ‘3.8’ services: flask-api: build: . ports: – “5000:5000” restart: always volumes: – ./logs:/app/logs # 挂载日志(跨平台) environment: – FLASK_ENV=prod networks: – flask-network networks: flask-network: driver: bridge 启动: # Windows docker-compose up -d # Linux docker-compose up -d
- Python 中「目录」和「包」的唯一区别就是是否有 __init__.py —— 没有这个文件,目录只是普通文件夹,无法被 import;有了它,目录才会被识别为Python 包,支持模块化导入。
- # 无 __init__.py 的情况(普通文件夹) flask-api/ └── app/ # 普通文件夹,无法 import ├── user.py └── order.py # 导入报错(Python 不识别 app 为包) from app import user # ModuleNotFoundError: No module named ‘app’ # 有 __init__.py 的情况(包) flask-api/ └── app/ # Python 包 ├── __init__.py # 空文件也生效 ├── user.py └── order.py # 导入成功 from app import user from app.user import user_bp
- 如果直接让用户导入 app/user.py 里的 user_bp,路径太长且暴露内部结构;可以在 app/__init__.py 中「导出」常用对象,让导入更简洁。 示例:简化多文件导入 # app/__init__.py # 从子模块导出核心对象 from app.user import user_bp from app.order import order_bp from app.utils.common import encrypt_password # 定义 __all__(配合 from app import * 时生效) __all__ = [“user_bp”, “order_bp”, “encrypt_password”] # 外部导入(简化前) from app.user import user_bp from app.order import order_bp from app.utils.common import encrypt_password # 外部导入(简化后) from app import user_bp, order_bp, encrypt_password # 或 from app import * # 仅导入 __all__ 中的对象
- __init__.py 在包被导入时自动执行,可以在这里完成包的初始化逻辑(如加载配置、初始化数据库、注册蓝图等)—— 这也是 Flask 多文件项目的核心用法。 示例:Flask 应用工厂(核心实战) # app/__init__.py from flask import Flask import os # 包导入时自动执行的初始化逻辑 def create_app(env: str = None): app = Flask(__name__) # 加载配置 env = env or os.getenv(“FLASK_ENV”, “dev”) if env == “prod”: app.config.from_object(“app.config.prod”) else: app.config.from_object(“app.config.dev”) # 统一注册所有蓝图(无需在 run.py 中逐个导入) from app.user import user_bp from app.order import order_bp app.register_blueprint(user_bp, url_prefix=”/api/user”) app.register_blueprint(order_bp, url_prefix=”/api/order”) return app # 可选:初始化数据库连接(全局生效) from app.utils.db import init_db init_db() # run.py(只需导入 create_app,无需关心内部模块) from app import create_app app = create_app() app.run()
- 多文件项目最容易遇到「循环导入」(如 user.py 导入 db.py,db.py 又导入 user.py),通过 __init__.py 延迟导入可解决。 示例:解决循环导入 # 问题场景:循环导入 # app/user.py from app.utils.db import db # 导入 db db.add_user(…) # app/utils/db.py from app.user import user_bp # 又导入 user_bp → 循环导入报错 # 解决方案:在 __init__.py 中延迟导入 # app/__init__.py def create_app(): app = Flask(__name__) # 延迟导入(直到函数调用时才导入,避免初始化时循环) from app.user import user_bp from app.utils.db import init_db init_db(app) # 把 app 传入 db 模块,避免 db 导入 user app.register_blueprint(user_bp) return app
- 可以在 __init__.py 中定义包的版本、作者等元数据,方便外部调用。 # app/__init__.py __version__ = “1.0.0” __author__ = “xxx” __description__ = “Flask 多文件 API 项目” # 外部获取元数据 import app print(app.__version__) # 1.0.0 print(app.__author__) # xxx
- 场景 init.py 写法 说明 仅标记为包 空文件 最简单,仅让目录可导入 简化导入 导出子模块对象 + 定义 all 外部导入更简洁 Flask 项目核心包 编写应用工厂函数 + 统一注册蓝图 / 初始化资源 多文件项目的标准用法 工具类包 导出常用工具函数 + 初始化全局资源 如 utils/init.py 避免循环导入 延迟导入(在函数内部导入子模块) 解决多文件依赖问题
-
- Python 3.3 引入了「隐式命名空间包」,即使没有 __init__.py,也能导入目录;但: 兼容性差(低版本 Python 不支持); 无法控制导出、初始化资源、解决循环导入; Flask/Django 等框架的工程化实践中,仍要求必须有 __init__.py(保证项目规范)。
- 不是!子包的 __init__.py 可以是空文件(仅标记为包),只有「根包」(如 app/__init__.py)需要写初始化逻辑。 示例:合理的分层写法 app/├── __init__.py # 核心逻辑(应用工厂、蓝图注册)├── user.py├── order.py└── utils/ # 子包 ├── __init__.py # 空文件(仅标记为包) ├── common.py └── db.py
- __init__.py 仅在包第一次被导入时执行一次,后续导入会复用已加载的模块(Python 模块缓存机制),无需担心性能问题。
- 核心结论 通俗解释 为什么要有? 让普通目录变成「Python 包」,支持导入 空文件行不行? 行(仅满足基础导入),但工程化项目建议写逻辑 Flask 项目中核心作用? 统一初始化应用、注册蓝图、简化导入、解决循环依赖 哪些目录需要? 所有需要被 import 的目录(如 app/、app/utils/) 简单来说:__init__.py 是 Python 模块化的「入口门牌号」—— 没有它,Python 找不到你的代码;有了它,你还能控制代码怎么被找到、怎么初始化。 到此这篇关于Python Flask实现多文件项目打包部署(Linux+Docker+Windows全环境)指南的文章就介绍到这了,更多相关Python Flask打包内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: 将Python Flask服务打包成Docker镜像并运行的完整指南 将python flask项目打包成可以运行的软件的全过程(包含报错解决) python flask项目打包成docker镜像发布的过程
目录
- 一、先规范多文件项目结构(核心前提)
- 核心文件示例(多文件关键)
- app/__init__.py(应用工厂,解决多模块导入)
- app/api/user.py(用户接口模块,多 py 文件示例)
- app/api/order.py(订单接口模块,多 py 文件示例)
- app/utils/common.py(工具类 1)
- app/utils/db.py(工具类 2,数据库示例)
- app/config/win.py(Windows 环境配置)
- app/config/prod.py(Linux 生产环境配置)
- run.py(统一启动入口)
- requirements.txt(跨平台依赖)
- 二、Windows 环境部署(多文件项目)
- 步骤 1:Windows 环境准备
- 步骤 2:创建虚拟环境(隔离依赖)
- 步骤 3:本地调试运行(开发环境)
- 步骤 4:Windows 生产环境部署(后台运行 + 进程守护)
- 方案 1:Waitress + Supervisor(推荐)
- 方案 2:NSSM(将 Flask 注册为 Windows 服务)
- 步骤 5:Windows 端口占用排查
- 三、Linux 环境部署(多文件项目)
- 步骤 1:上传多文件项目到 Linux
- 步骤 2:虚拟环境 + 依赖安装
- 步骤 3:Gunicorn 启动(多文件兼容)
- 步骤 4:Supervisor 配置(适配多文件)
- 四、Docker 部署(跨平台多文件项目)
- 步骤 1:优化 Dockerfile(多文件兼容)
- 步骤 2:Windows 下构建 Docker 镜像
- 步骤 3:启动 Docker 容器(跨平台通用)
- 步骤 4:Docker Compose(多容器 + 多文件)
- 五、多文件项目部署关键注意事项
- 六、常见问题排查(多文件 + 跨平台)
- init.py 的核心作用与使用场景详解
- init.py 的核心作用(为什么必须有)
- 作用 1:标记目录为 Python 包(最基础)
- 作用 2:控制包的导出(简化导入)
- 作用 3:初始化包的资源(统一加载)
- 作用 4:解决循环导入问题
- 作用 5:定义包的元数据(可选)
- 不同场景下init.py 的写法
- 常见误区(避坑)
- 误区 1:Python 3.3+ 不需要init.py?
- 误区 2:所有init.py 都要写复杂逻辑?
- 误区 3:init.py 执行多次?
- 总结
针对多 .py 文件的 Flask 项目,本文在原有部署方案基础上,补充多文件项目结构规范、Windows 环境部署、跨平台打包等核心内容,确保多文件项目在 Linux/Docker/Windows 下都能稳定运行。
多 .py 文件的关键是模块化拆分 + 避免循环导入 + 统一入口,示例结构如下(覆盖工具类、多蓝图、配置分层):
plaintext
flask-multi-api/
├── app/ # 核心代码包
│ ├── __init__.py # 应用工厂(核心)
│ ├── api/ # 接口模块(多蓝图)
│ │ ├── __init__.py
│ │ ├── user.py # 用户相关接口
│ │ └── order.py # 订单相关接口
│ ├── utils/ # 工具类(多py文件)
│ │ ├── __init__.py
│ │ ├── common.py # 通用工具(加密、校验)
│ │ └── db.py # 数据库操作
│ └── config/ # 配置分层(跨环境)
│ ├── __init__.py
│ ├── base.py # 基础配置(通用)
│ ├── dev.py # 开发环境(Windows)
│ ├── prod.py # 生产环境(Linux/Docker)
│ └── win.py # Windows 特有配置
├── run.py # 统一启动入口
├── requirements.txt # 依赖清单(跨平台)
├── Dockerfile # Docker 构建文件
├── .dockerignore # Docker 忽略文件
├── start.bat # Windows 启动脚本
└── supervisord.conf # Linux 进程守护配置
from flask import Flask
import os
def create_app(env: str = None):
"""
应用工厂函数(支持指定环境:dev/prod/win)
:param env: 环境标识(dev=开发/Windows, prod=生产/Linux)
"""
app = Flask(__name__)
# 加载配置(根据环境自动切换)
env = env or os.getenv("FLASK_ENV", "dev")
if env == "dev" or env == "win":
app.config.from_object("app.config.win")
elif env == "prod":
app.config.from_object("app.config.prod")
else:
app.config.from_object("app.config.base")
# 注册多蓝图(拆分的接口模块)
from app.api.user import user_bp
from app.api.order import order_bp
app.register_blueprint(user_bp, url_prefix="/api/user")
app.register_blueprint(order_bp, url_prefix="/api/order")
return app
from flask import Blueprint, jsonify, request
from app.utils.common import encrypt_password # 导入工具类(多py文件调用)
user_bp = Blueprint("user", __name__)
# 用户登录接口
@user_bp.post("/login")
def login():
data = request.get_json()
username = data.get("username")
password = encrypt_password(data.get("password")) # 调用工具类
return jsonify({
"code": 200,
"msg": "登录成功",
"data": {"username": username, "token": f"token_{username}"}
})
# 用户信息接口
@user_bp.get("/info")
def get_user_info():
user_id = request.args.get("id")
return jsonify({
"code": 200,
"data": {"id": user_id, "name": "张三", "age": 25}
})
from flask import Blueprint, jsonify
from app.utils.db import get_order_data # 导入数据库工具类
order_bp = Blueprint("order", __name__)
# 订单列表接口
@order_bp.get("/list")
def get_order_list():
orders = get_order_data() # 调用工具类
return jsonify({
"code": 200,
"data": orders
})
import hashlib
def encrypt_password(password: str) -> str:
"""密码加密工具"""
return hashlib.md5((password + "salt123").encode()).hexdigest()
def check_params(params: dict, required: list) -> bool:
"""参数校验工具"""
return all([p in params for p in required])
def get_order_data():
"""模拟数据库查询订单数据"""
return [
{"order_id": "1001", "amount": 99.9, "status": "paid"},
{"order_id": "1002", "amount": 199.9, "status": "unpaid"}
]
DEBUG = True # Windows 开发环境开启DEBUG
HOST = "127.0.0.1" # Windows 本地访问
PORT = 5000
SECRET_KEY = "win-secret-key-123"
# Windows 特有配置(如本地数据库路径)
DB_PATH = "C:/flask-api/data.db"
DEBUG = False # 生产环境关闭DEBUG
HOST = "0.0.0.0" # 允许外部访问
PORT = 5000
SECRET_KEY = "prod-secret-key-456"
# Linux 特有配置(如服务器数据库地址)
DB_PATH = "/opt/flask-api/data.db"
import sys
from app import create_app
if __name__ == "__main__":
# 识别运行环境(Windows/Linux)
env = "win" if sys.platform == "win32" else "prod"
# 手动指定环境:python run.py prod
if len(sys.argv) > 1:
env = sys.argv[1]
app = create_app(env=env)
app.run(
host=app.config["HOST"],
port=app.config["PORT"],
debug=app.config["DEBUG"]
)
# 核心依赖(跨平台兼容)
Flask==2.3.3
gunicorn==21.2.0 # Linux/Docker用(Windows可选)
waitress==2.1.2 # Windows替代Gunicorn的WSGI服务器
requests==2.31.0
pywin32>=306 # Windows 进程守护(可选)
supervisor==4.2.5 # Linux 进程守护(Windows也可装)
Windows 部署分开发环境(本地调试) 和生产环境(服务运行) 两种场景,重点解决 “多文件导入”“进程守护”“端口占用” 问题。
安装 Python 3.8+(勾选 “Add Python to PATH”);
验证环境:
python --version # 或 python3 --version pip --version
解压 / 克隆项目到本地(如 D:flask-multi-api)。
# 进入项目目录
cd D:flask-multi-api
# 创建虚拟环境
python -m venv venv
# 激活虚拟环境(Windows 命令行)
venvScriptsactivate.bat
# 如果是PowerShell,执行:
# venvScriptsActivate.ps1
# 安装依赖
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 方式1:直接启动(自动识别Windows环境)
python run.py
# 方式2:手动指定win环境
python run.py win
测试接口(浏览器 / Postman/curl):
# 测试用户接口 curl "http://127.0.0.1:5000/api/user/info?id=1" # 测试订单接口 curl "http://127.0.0.1:5000/api/order/list"
Flask 内置服务器不适合生产,Windows 用 waitress 替代 Gunicorn,结合 Supervisor 或 NSSM 实现后台运行。
安装 Supervisor(Windows 版):
pip install supervisor
创建 supervisord.conf 配置文件(项目根目录):
[unix_http_server]
file = NUL # Windows 无需unix socket
[inet_http_server]
port = 127.0.0.1:9001 # Supervisor 管理端口
username = admin
password = 123456
[supervisord]
logfile = D:flask-multi-apilogssupervisord.log
logfile_maxbytes = 50MB
logfile_backups = 10
loglevel = info
pidfile = D:flask-multi-apisupervisord.pid
nodaemon = false # 后台运行
minfds = 1024
minprocs = 200
environment = FLASK_ENV="win"
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl = http://127.0.0.1:9001
# Flask 应用配置
[program:flask-api]
directory = D:flask-multi-api
command = D:flask-multi-apivenvScriptswaitress-serve.exe --host=0.0.0.0 --port=5000 run:create_app('win')
autostart = true
autorestart = true
startretries = 3
stdout_logfile = D:flask-multi-apilogsflask-api.log
stdout_logfile_maxbytes = 50MB
stdout_logfile_backups = 10
redirect_stderr = true
创建日志目录:
mkdir D:flask-multi-apilogs
启动 Supervisor:
# 生成默认配置(可选) echo_supervisord_conf > supervisord.conf # 启动Supervisor supervisord -c supervisord.conf # 管理命令 supervisorctl -c supervisord.conf status # 查看状态 supervisorctl -c supervisord.conf start flask-api # 启动应用 supervisorctl -c supervisord.conf restart flask-api # 重启
下载 NSSM,解压到 D:nssm;
注册为 Windows 服务:
# 进入NSSM目录 cd D:nssmwin64 # 注册服务(名称:FlaskAPI) nssm install FlaskAPI D:flask-multi-apivenvScriptspython.exe # 设置服务参数 nssm set FlaskAPI AppParameters "run.py win" nssm set FlaskAPI AppDirectory D:flask-multi-api nssm set FlaskAPI Start SERVICE_AUTO_START # 开机自启 nssm set FlaskAPI AppStdout D:flask-multi-apilogsstdout.log nssm set FlaskAPI AppStderr D:flask-multi-apilogsstderr.log
启动 / 管理服务:
nssm start FlaskAPI # 启动 nssm stop FlaskAPI # 停止 nssm restart FlaskAPI # 重启 nssm remove FlaskAPI confirm # 卸载
# 查看5000端口占用
netstat -ano | findstr :5000
# 杀死占用进程(PID替换为实际值)
taskkill /F /PID 1234
在原有 Linux 部署基础上,适配多文件结构,核心步骤不变,仅补充细节:
# 创建目录
mkdir -p /opt/flask-multi-api
# 上传项目(用scp/rz/git)
scp -r D:flask-multi-api root@<LinuxIP>:/opt/
cd /opt/flask-multi-api
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 直接启动(自动识别Linux环境)
gunicorn -w 4 -b 0.0.0.0:5000 "run:create_app('prod')"
修改 /etc/supervisord.d/flask-api.ini:
[program:flask-api]
directory=/opt/flask-multi-api
command=/opt/flask-multi-api/venv/bin/gunicorn -w 4 -b 0.0.0.0:5000 "run:create_app('prod')"
autostart=true
autorestart=true
user=root
stdout_logfile=/var/log/flask-api.log
重启 Supervisor:
supervisorctl reload supervisorctl start flask-api
Docker 部署可统一 Windows/Linux 环境,核心是优化 Dockerfile 适配多文件结构,支持跨平台构建。
# 基础镜像(跨平台兼容)
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 环境变量(生产环境)
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV FLASK_ENV=prod
# 安装系统依赖
RUN apt update && apt install -y --no-install-recommends gcc
&& rm -rf /var/lib/apt/lists/*
# 复制依赖清单
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 复制所有多文件代码(关键:保留目录结构)
COPY . .
# 暴露端口
EXPOSE 5000
# 启动命令(多文件入口)
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "run:create_app('prod')"]
安装 Docker Desktop(Windows),开启 WSL2 后端;
进入项目目录,构建镜像:
docker build -t flask-multi-api:v1 .
# Windows/Linux 通用命令
docker run -d
--name flask-multi-api
-p 5000:5000
--restart=always
-v /var/log/flask-api:/app/logs # 挂载日志(Linux)
# Windows 挂载日志:-v D:flask-multi-apilogs:/app/logs
flask-multi-api:v1
编写 docker-compose.yml:
version: '3.8'
services:
flask-api:
build: .
ports:
- "5000:5000"
restart: always
volumes:
- ./logs:/app/logs # 挂载日志(跨平台)
environment:
- FLASK_ENV=prod
networks:
- flask-network
networks:
flask-network:
driver: bridge
启动:
# Windows docker-compose up -d # Linux docker-compose up -d
导入路径问题:
- 确保所有
.py文件所在目录有__init__.py(空文件也可); - 避免相对导入,统一用绝对导入(如
from app.utils.common import xxx)。
跨平台配置:
- 通过
FLASK_ENV环境变量区分 Windows/Linux 配置; - 路径用
os.path或pathlib适配(避免硬编码C:/或/opt/)。
依赖跨平台兼容:
避免依赖仅支持单一系统(如 pywin32 仅 Windows,在 Linux/Docker 中跳过);
requirements.txt 中可通过 ; sys_platform == "win32" 区分依赖:
pywin32>=306 ; sys_platform == "win32" gunicorn==21.2.0 ; sys_platform != "win32" waitress==2.1.2 ; sys_platform == "win32"
Docker 跨平台构建:
- Windows 下构建 Linux 镜像:开启 Docker Desktop 的 “Buildx” 功能;
- 避免在 Dockerfile 中使用 Windows 特有命令(如
COPY C:/xxx)。
日志持久化:多文件项目日志需统一目录,Docker/Windows/Linux 均挂载日志目录,避免日志丢失。
| 问题场景 | 原因 | 解决方案 |
|---|---|---|
| 多文件导入报错 ModuleNotFoundError | 缺少 __init__.py 或导入路径错误 | 给所有包目录加 __init__.py,使用绝对导入 |
| Windows 启动 Supervisor 报错 | 路径用了 / 而非 | 配置文件中路径用 D:xxx 或 /d/xxx |
| Docker 构建失败(多文件) | 复制时遗漏目录 | COPY . . 确保复制所有目录,检查 .dockerignore 未忽略核心文件 |
| Linux 下 Gunicorn 启动报错 create_app not found | 入口函数调用格式错误 | 用双引号包裹:"run:create_app('prod')" |
| Windows 服务启动后无响应 | Waitress 命令错误 | 检查 waitress-serve 路径,确保调用 create_app 返回 app 实例 |
通过以上方案,多 .py 文件的 Flask 项目可在 Windows(开发 / 生产)、Linux(生产)、Docker(跨平台)下稳定部署,兼顾模块化拆分和环境适配。
在 Python 项目(尤其是 Flask 多文件项目)中,__init__.py 是包(Package) 的核心标识文件,理解它的作用能彻底解决多文件导入、模块化拆分的问题。以下从「核心作用」「实战场景」「常见误区」三个维度讲清楚:
Python 中「目录」和「包」的唯一区别就是是否有 __init__.py —— 没有这个文件,目录只是普通文件夹,无法被 import;有了它,目录才会被识别为Python 包,支持模块化导入。
# 无 __init__.py 的情况(普通文件夹)
flask-api/
└── app/ # 普通文件夹,无法 import
├── user.py
└── order.py
# 导入报错(Python 不识别 app 为包)
from app import user # ModuleNotFoundError: No module named 'app'
# 有 __init__.py 的情况(包)
flask-api/
└── app/ # Python 包
├── __init__.py # 空文件也生效
├── user.py
└── order.py
# 导入成功
from app import user
from app.user import user_bp
如果直接让用户导入 app/user.py 里的 user_bp,路径太长且暴露内部结构;可以在 app/__init__.py 中「导出」常用对象,让导入更简洁。
示例:简化多文件导入
# app/__init__.py # 从子模块导出核心对象 from app.user import user_bp from app.order import order_bp from app.utils.common import encrypt_password # 定义 __all__(配合 from app import * 时生效) __all__ = ["user_bp", "order_bp", "encrypt_password"]
# 外部导入(简化前) from app.user import user_bp from app.order import order_bp from app.utils.common import encrypt_password # 外部导入(简化后) from app import user_bp, order_bp, encrypt_password # 或 from app import * # 仅导入 __all__ 中的对象
__init__.py 在包被导入时自动执行,可以在这里完成包的初始化逻辑(如加载配置、初始化数据库、注册蓝图等)—— 这也是 Flask 多文件项目的核心用法。
示例:Flask 应用工厂(核心实战)
# app/__init__.py
from flask import Flask
import os
# 包导入时自动执行的初始化逻辑
def create_app(env: str = None):
app = Flask(__name__)
# 加载配置
env = env or os.getenv("FLASK_ENV", "dev")
if env == "prod":
app.config.from_object("app.config.prod")
else:
app.config.from_object("app.config.dev")
# 统一注册所有蓝图(无需在 run.py 中逐个导入)
from app.user import user_bp
from app.order import order_bp
app.register_blueprint(user_bp, url_prefix="/api/user")
app.register_blueprint(order_bp, url_prefix="/api/order")
return app
# 可选:初始化数据库连接(全局生效)
from app.utils.db import init_db
init_db()
# run.py(只需导入 create_app,无需关心内部模块) from app import create_app app = create_app() app.run()
多文件项目最容易遇到「循环导入」(如 user.py 导入 db.py,db.py 又导入 user.py),通过 __init__.py 延迟导入可解决。
示例:解决循环导入
# 问题场景:循环导入 # app/user.py from app.utils.db import db # 导入 db db.add_user(...) # app/utils/db.py from app.user import user_bp # 又导入 user_bp → 循环导入报错
# 解决方案:在 __init__.py 中延迟导入
# app/__init__.py
def create_app():
app = Flask(__name__)
# 延迟导入(直到函数调用时才导入,避免初始化时循环)
from app.user import user_bp
from app.utils.db import init_db
init_db(app) # 把 app 传入 db 模块,避免 db 导入 user
app.register_blueprint(user_bp)
return app
可以在 __init__.py 中定义包的版本、作者等元数据,方便外部调用。
# app/__init__.py __version__ = "1.0.0" __author__ = "xxx" __description__ = "Flask 多文件 API 项目"
# 外部获取元数据 import app print(app.__version__) # 1.0.0 print(app.__author__) # xxx
| 场景 | init.py 写法 | 说明 |
|---|---|---|
| 仅标记为包 | 空文件 | 最简单,仅让目录可导入 |
| 简化导入 | 导出子模块对象 + 定义 all | 外部导入更简洁 |
| Flask 项目核心包 | 编写应用工厂函数 + 统一注册蓝图 / 初始化资源 | 多文件项目的标准用法 |
| 工具类包 | 导出常用工具函数 + 初始化全局资源 | 如 utils/init.py |
| 避免循环导入 | 延迟导入(在函数内部导入子模块) | 解决多文件依赖问题 |
Python 3.3 引入了「隐式命名空间包」,即使没有 __init__.py,也能导入目录;但:
- 兼容性差(低版本 Python 不支持);
- 无法控制导出、初始化资源、解决循环导入;
- Flask/Django 等框架的工程化实践中,仍要求必须有
__init__.py(保证项目规范)。
不是!子包的 __init__.py 可以是空文件(仅标记为包),只有「根包」(如 app/__init__.py)需要写初始化逻辑。
示例:合理的分层写法
app/
├── __init__.py # 核心逻辑(应用工厂、蓝图注册)
├── user.py
├── order.py
└── utils/ # 子包
├── __init__.py # 空文件(仅标记为包)
├── common.py
└── db.py
__init__.py 仅在包第一次被导入时执行一次,后续导入会复用已加载的模块(Python 模块缓存机制),无需担心性能问题。
| 核心结论 | 通俗解释 |
|---|---|
| 为什么要有? | 让普通目录变成「Python 包」,支持导入 |
| 空文件行不行? | 行(仅满足基础导入),但工程化项目建议写逻辑 |
| Flask 项目中核心作用? | 统一初始化应用、注册蓝图、简化导入、解决循环依赖 |
| 哪些目录需要? | 所有需要被 import 的目录(如 app/、app/utils/) |
简单来说:__init__.py 是 Python 模块化的「入口门牌号」—— 没有它,Python 找不到你的代码;有了它,你还能控制代码怎么被找到、怎么初始化。
到此这篇关于Python Flask实现多文件项目打包部署(Linux+Docker+Windows全环境)指南的文章就介绍到这了,更多相关Python Flask打包内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- 将Python Flask服务打包成Docker镜像并运行的完整指南
- 将python flask项目打包成可以运行的软件的全过程(包含报错解决)
- python flask项目打包成docker镜像发布的过程