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

Flask集成peewee与APScheduler启动触发任务报连接已打开错误

解决Flask+Peewee+APScheduler的「Connection already opened」错误

这个问题的核心在于APScheduler的定时任务运行在Flask请求上下文之外,而Flask-Peewee的连接池默认和请求上下文绑定——每次HTTP请求会自动获取连接,请求结束后自动释放。但定时任务(包括你启动时手动调用的scheduler.run_job)不在这个流程里,导致数据库连接没有被正确管理,最终触发连接重复打开的错误。

下面是具体的解决步骤:

1. 给定时任务手动添加Flask应用上下文

修改你的任务函数,在执行数据库操作前手动推送Flask应用上下文,让Peewee能正确识别并管理连接:

from flask import current_app
from your_app_module import app  # 导入你已创建的应用实例

def do_something_job():
    # 手动推送应用上下文,包裹所有数据库操作
    with app.app_context():
        new = NewModel(seed=new_seed())
        new.save()
        old_list = NewModel.select()
        for old in old_list:
            if old.id != new.id:
                expired = OldModel(
                    seed=old.seed,
                    created_at=old.created_at,
                    expired_at=datetime.datetime.utcnow()
                )
                expired.save()
                old.delete_instance()

如果你的应用用工厂模式创建,也可以在任务里动态获取应用实例后推送上下文:

from your_app_module import create_app, Config

def do_something_job():
    app = create_app(Config)
    with app.app_context():
        # 数据库操作代码...

2. 调整启动时任务执行的方式

你现在在create_app里直接调用scheduler.run_job,此时应用上下文还未完全初始化。可以改用scheduler.add_job并设置next_run_time=datetime.now(),让任务自动立即执行一次,同时确保在正确的上下文环境中运行:

修改app.py代码:

from datetime import datetime

scheduler = APScheduler()
db = FlaskDB()

def create_app(config_object=Config):
    app = Flask(__name__.split('.')[0])
    app.config.from_object(config_object)
    db.init_app(app)
    
    scheduler.init_app(app)
    
    # 添加任务时设置立即执行,之后每8小时循环
    scheduler.add_job(
        id='myjob',
        func='app.jobs:do_something_job',
        trigger='interval',
        hours=8,
        next_run_time=datetime.now()
    )
    scheduler.start()
    
    return app

app = create_app(Config)

这样就不需要手动调用scheduler.run_job,APScheduler会自动处理第一次执行的上下文问题。

3. 验证连接池配置

你的数据库URL配置是合理的,stale_timeout=300会自动回收闲置超过5分钟的连接,避免连接泄漏:

DATABASE = 'postgresext+pool://user:password@localhost:5432/dev?max_connections=32&stale_timeout=300'

错误根源解释

当你在没有应用上下文的情况下执行Peewee操作时,连接不会被自动归还给连接池。第一次任务执行可能看似成功,但连接未被释放,后续HTTP请求尝试获取连接时,就会遇到「Connection already opened」错误——因为之前的连接还被占用,没有正确回收。通过手动添加应用上下文,Peewee就能在任务执行完成后自动释放连接,回到连接池供后续请求使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:07:35