1

在某些任务(如电子邮件发送)尚未完成之前,flask 如何渲染页面?

问题

在我们的例子中,当用户向服务器提交注册信息时,服务器会先发送一封认证邮件,然后呈现一个成功页面。但是邮件发送总是需要3~5秒,也就是说他提交注册信息后至少需要3秒才能得到回复。

我们所做的

1. 信号

我们尝试发送一个信号并触发一个邮件发送功能来做这件事:

if approved:
    # ...

    send_activation_signal.send(email)

    login_user(u)
    return redirect(url_for('register_success'))

结果

一切都很好,除了在 r​​egister_success 页面呈现之前至少需要 3 秒。

2. 分叉一个线程

分叉一个线程以完成电子邮件发送

t = threading.Thread(target = send_activation, args = (email, username, email_confirm_code, ))
t.start()

结果

但看起来请求上下文没有以正确的方式处理。

> Exception in thread Thread-2: Traceback (most recent call last):  
> File
> "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py",
> line 552, in __bootstrap_inner
>     self.run()   File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py",
> line 505, in run
>     self.__target(*self.__args, **self.__kwargs)   File "/Users/arthasshih/flask/happyvs/main_app/views/user.py", line 267, in
> send_activation
>     app.logger.debug("sending #############")   File "/Users/arthasshih/virtual_evns/normal/lib/python2.7/site-packages/Werkzeug-0.8.3-py2.7.egg/werkzeug/local.py",
> line 336, in __getattr__
>     return getattr(self._get_current_object(), name)   File "/Users/arthasshih/virtual_evns/normal/lib/python2.7/site-packages/Werkzeug-0.8.3-py2.7.egg/werkzeug/local.py",
> line 295, in _get_current_object
>     return self.__local()   File "/Users/arthasshih/virtual_evns/normal/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/globals.py",
> line 19, in _lookup_object
>     raise RuntimeError('working outside of request context') RuntimeError: working outside of request context
4

1 回答 1

4

在烧瓶中设置电子邮件发送时,我也遇到了这个问题,但问题不是烧瓶。如果您希望烧瓶在完成发送邮件任务之前返回,则此过程必须异步运行,但它在这里同步运行,所以这就是等待的原因。

解决方案是使用Celery: Distributed Task Queue。这段文字来自他们的主页:

它是一个基于分布式消息传递的异步任务队列/作业队列。任务可以异步执行(在后台)或同步执行(等待就绪)。

还有一个名为Flask-Celery的 Flask 扩展,它可以轻松地将 celery 与烧瓶集成。

简单地将邮件发送任务添加到 celery 的异步任务队列和渲染页面。如果任务失败,您必须确保 celery 生成一些错误日志,否则无论是否发送邮件,您都不会。

于 2012-06-17T17:58:27.890 回答