首页 > 解决方案 > RuntimeError (_app_ctx_err_msg):在从线程发送邮件时在应用程序上下文之外工作

问题描述

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

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.

标签: pythonmultithreadingflaskflask-mail

解决方案


调试后我发现问题出在“current_app”上,这是一个线程本地值,当你将它传递给 __process 时,我们并没有传递实际的 app 对象。

这可以通过使用代理解决,使用 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()

推荐阅读