如何在Python Flask框架中运行循环任务?

2024-05-15 03:36:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在建立一个网站,向访问者提供一些信息。通过每5秒轮询两个外部api,在后台聚合此信息。我现在的工作方式是使用APScheduler作业。我最初更喜欢APScheduler,因为它使整个系统更易于移植(因为我不需要在新机器上设置cron作业)。我按如下方式启动轮询功能:

from apscheduler.scheduler import Scheduler

@app.before_first_request
def initialize():
    apsched = Scheduler()
    apsched.start()

    apsched.add_interval_job(checkFirstAPI, seconds=5)
    apsched.add_interval_job(checkSecondAPI, seconds=5)
    apsched.add_interval_job(checkThirdAPI, seconds=5)

这有点管用,但有点麻烦:

  1. 首先,这意味着间隔作业在烧瓶上下文之外运行。到目前为止,这还不是什么大问题,但当调用端点失败时,我希望系统向我发送一封电子邮件(说“嘿,调用API X失败”)。但是,由于它不在Flask上下文中运行,因此它抱怨不能执行flask-mailRuntimeError('working outside of application context'))。
  2. 其次,我想知道当我不再使用Flask内置的调试服务器,而是一个有4个工人的生产服务器时,这将如何表现。那么它会开始每项工作四次吗?

总之,我觉得应该有更好的方法来运行这些重复的任务,但我不确定如何运行。有没有人对这个问题有一个有趣的解决办法?欢迎所有小费!

[编辑] 我刚刚读到关于Celery及其schedules的文章。虽然我不知道芹菜和APScheduler有什么不同,也不知道它是否能解决我的两点,但我想知道是否有人读到这篇文章,认为我应该对芹菜进行更多的调查?

[结论] 大约两年后,我读到这篇文章,我想我可以让你们知道我的结局。我认为“蓝辣椒”说得对,我不应该和烧瓶生态系统绑得那么紧。所以我选择了每分钟都运行的常规cron作业,这些作业是使用Ansible设置的。虽然这使它变得更复杂(我需要学习Ansible并转换一些代码,以便每分钟运行它就足够了),但我认为这更健壮。 我目前正在使用awesomepythonr-rq来排队a-sync作业(检查api和发送电子邮件)。我刚刚发现了rq-scheduler。我还没有测试它,但它似乎做的正是我首先需要的。所以也许这是给未来读者的一个提示。

剩下的,我只希望你们大家有一个美好的一天!


Tags: addapi信息烧瓶系统作业方式job
1条回答
网友
1楼 · 发布于 2024-05-15 03:36:31

(一)

可以使用app.app_context()上下文管理器设置应用程序上下文。我想用法应该是这样的:

from apscheduler.scheduler import Scheduler

def checkSecondApi():
    with app.app_context():
        # Do whatever you were doing to check the second API

@app.before_first_request
def initialize():
    apsched = Scheduler()
    apsched.start()

    apsched.add_interval_job(checkFirstAPI, seconds=5)
    apsched.add_interval_job(checkSecondAPI, seconds=5)
    apsched.add_interval_job(checkThirdAPI, seconds=5)

或者,你可以用一个装饰工

def with_application_context(app):
    def inner(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            with app.app_context():
                return func(*args, **kwargs)
        return wrapper
    return inner

@with_application_context(app)
def checkFirstAPI():
    # Check the first API as before

(二)

是的,它仍然有效。唯一的(显著的)区别是,您的应用程序不会直接与世界通信;它将通过反向代理或通过fastcgi/uwsgi/whatever进行通信。唯一需要注意的是,如果有多个应用程序实例正在启动,则将创建多个调度程序。为了管理这一点,我建议您将后端任务移出Flask应用程序,并使用一个为定期运行任务而设计的工具(如芹菜)。这样做的缺点是你不能使用Flask Mail之类的东西,但在我看来,与Flask生态系统如此紧密地联系在一起并不太好;在标准的、非Flask的邮件库中使用Flask Mail有什么好处?

此外,与拥有一个单一的web应用程序相比,拆分应用程序可以更容易地根据需要扩展单个组件。

相关问题 更多 >

    热门问题