在Flask应用中创建、管理和终止后台任务

3 投票
2 回答
4623 浏览
提问于 2025-04-18 04:20

我正在开发一个Flask网页应用,用户可以在里面启动和管理一些进程。这些进程会进行一些比较复杂的计算,可能需要几天的时间。在进程运行的时候,它会把一些部分结果保存到文件中,以便后续使用。

当用户启动一个新进程时,我会创建一个新的线程,并把这个线程的句柄保存在Flask的全局变量flask.g里。

def add_thread(thread_handle):
    ctx = app.app_context()
    threads = flask.g.get("threads", [])
    threads.append(thread_handle)
    g.threads = threads
    ctx.push()

之后,当需要的时候,用户可以终止这个长时间运行的进程。

def kill_thread(idx):
    ctx = app.app_context()
    threads = flask.g.get("threads", [])
    threads.pop(idx).terminate()
    g.threads = threads
    ctx.push()

我必须使用ctx.push()来存储线程的列表,这样在下一个请求时,这个列表就可以使用了。但是这样做在添加新线程时会抛出关于应用上下文的异常。

Traceback (most recent call last):
  File "/Users/mirobeka/.virtualenvs/cellular/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/mirobeka/.virtualenvs/cellular/lib/python2.7/site-packages/flask/app.py", line 1825, in wsgi_app
    ctx.auto_pop(error)
  File "/Users/mirobeka/.virtualenvs/cellular/lib/python2.7/site-packages/flask/ctx.py", line 374, in auto_pop
    self.pop(exc)
  File "/Users/mirobeka/.virtualenvs/cellular/lib/python2.7/site-packages/flask/ctx.py", line 366, in pop
    app_ctx.pop(exc)
  File "/Users/mirobeka/.virtualenvs/cellular/lib/python2.7/site-packages/flask/ctx.py", line 178, in pop
    % (rv, self)
AssertionError: Popped wrong app context.  (<flask.ctx.AppContext object at 0x10fb99c50> instead of <flask.ctx.AppContext object at 0x10fa60150>)

这让我觉得这个解决方案有点不太对劲,可能在后续开发中会遇到麻烦。我在考虑把线程句柄存储在文件或数据库中,但锁对象是不能被序列化的。

有没有什么设计模式可以用来管理我所描述的这些活跃的Python对象呢?

2 个回答

0

或者可以使用 rq,我觉得它比 celery 简单十倍。如果你在那遇到类似的问题,我在这里发布了我的解决方案 这里

4

你最好使用 celery(celeryproject.org)来处理这类任务。它在实际生产环境中被广泛使用,所以后续开发时不会遇到死胡同。它提供了管理后台任务所需的一切功能,还有很多其他的好处。这里有关于如何 将它与flask结合使用 的介绍。

撰写回答