RuntimeError(_app_ctx_err_msg):在从线程发送邮件时,在应用程序上下文之外工作

时间:2019-03-29 12:13:54

标签: python multithreading flask flask-mail

我正在尝试使用烧瓶邮件发送电子邮件,这是我用来发送邮件的代码片段

def send_async_email(app, msg):
    with app.app_context():
        mail.send(msg)

def send_email(subject, recipients, text_body=None, html_body=None):
    msg = Message(subject, recipients=recipients)
    msg.body = text_body
    msg.html = html_body
    thr = Thread(target=send_async_email, args=[current_app, msg])
    thr.start()

运行此代码时,出现以下错误

Exception in thread Thread-9:
Traceback (most recent call last):
  File "C:\Python37\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Python37\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "..\flask_demo\flaskdemo\common_utils.py", line 7, in send_async_email
    with app.app_context():
  File "..\flask_demo\venv\lib\site-packages\werkzeug\local.py", line 348, in __getattr__
    return getattr(self._get_current_object(), name)
  File "..\flask_demo\venv\lib\site-packages\werkzeug\local.py", line 307, in _get_current_object
    return self.__local()
  File "..\flask_demo\venv\lib\site-packages\flask\globals.py", line 51, in _find_app
    raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.

1 个答案:

答案 0 :(得分:0)

调试后,我发现问题出在“ current_app”,这是线程局部值,当您将其传递给__process时,我们没有传递实际的应用程序对象。

这可以通过使用代理解决,使用current_app._get_current_object()。有关更多信息,请访问http://flask.pocoo.org/docs/1.0/reqcontext/#notes-on-proxies

现在,代码看起来像这样

def send_email(subject, recipients, text_body=None, html_body=None):
    msg = Message(subject, recipients=recipients)
    msg.body = text_body
    msg.html = html_body
    app = current_app._get_current_object()
    thr = Thread(target=send_async_email, args=[app, msg])
    thr.start()