在学习Flask的时候,《Flask Web开发》这本书中有一个异步发送email的例子,
其中用到了线程

from . import mail,create_app

def send_async_email(app,msg):
with app.app_context():
mail.send(msg) def send_email(to,subject,template,**kwargs):
msg = Message(current_app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,
sender=current_app.config['FLASKY_MAIL_SENDER'], recipients=[to])
msg.body = render_template(template + '.txt', **kwargs)
msg.html = render_template(template + '.txt', **kwargs)
#with current_app.app_context():
# mail.send(msg)
thr = Thread(target=send_async_email, args=(current_app, msg))
thr.start()
return thr

发送邮件总是提示错误
RuntimeError: Working outside of application context.
后来查找资料才知道是传递current_app的问题

current_app在 Flask是一个代理,如果你看 Flask源码的话会发现其实它外部包裹的是这样的:

def _find_app():
top = _app_ctx_stack.top
if top is None:
raise RuntimeError(_app_ctx_err_msg)
return top.app ... current_app = LocalProxy(_find_app)

这个 LocalProxy就不展开讲了,但是我可以告诉你这个LocalProxy的作用就是可以根据线程/协程返回对应当前协程/线程的对象,也就是说
线程 A 往 LocalProxy 中塞入 A
线程 B 往 LocalProxy 中塞入 B
无论在是什么地方,线程 A 永远取到得是 A,线程 B 取到得永远是 B

这就是在 Flask中可以在代码中直接使用 request、current_app这样的变量的底层原因。
所以,因为这里开了一个新线程,如果你不传真实对象过去,那么你在线程里面使用 current_app将获取不到对象,因为他没有 flask 上下文。

获取真实对象Flask提供了一个方法:
_get_current_object()
官方文档是这样解释:

Return the current object. This is useful if you want the real object behind the proxy at a time for performance reasons or because you want to pass the object into a different context.

修改send_email函数后代码如下:

def send_email(to,subject,template,**kwargs):
msg = Message(current_app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,
sender=current_app.config['FLASKY_MAIL_SENDER'], recipients=[to])
msg.body = render_template(template + '.txt', **kwargs)
msg.html = render_template(template + '.txt', **kwargs)
#with current_app.app_context():
# mail.send(msg)
#current_app只是一个代理获取而已,传递给其它子线程获取到的依然是子线程的上下文
# 必须_get_current_object线获取到原始对象再传递过去
app = current_app._get_current_object()
thr = Thread(target=send_async_email, args=(app, msg))
thr.start()
return thr

这样就能异步发送邮件成功了

转自:https://www.jianshu.com/p/acaf646f537c

Python3关于current_app传递给子线程的更多相关文章

  1. ThreadLocal解析:父线程的本地变量不能传递到子线程详解

    众所周知,ThreadLocal类是java提供线程本地变量的工具类.但父线程的本地变量却不能被子线程使用,代码如下: public static void main(String[] args) { ...

  2. InheritableThreadLocal——父线程传递本地变量到子线程的解决方式及分析

    转自https://blog.csdn.net/hewenbo111/article/details/80487252 上一个博客提到ThreadLocal变量的基本使用方式,可以看出ThreadLo ...

  3. Qt自己定义事件实现及子线程向主线程传送事件消息

    近期在又一次学习Qt的时候,由于要涉及到子线程与主线程传递消息,所以便琢磨了一下.顺便把有用的记录下来,方便自己以后查询及各位同仁的參考! 特此声明,本篇博文主要讲述有用的,也就是直接说明怎么实现,就 ...

  4. C#子线程执行完后通知主线程

    其实这个比较简单,子线程怎么通知主线程,就是让子线程做完了自己的事儿就去干主线程的转回去干主线程的事儿. 那么怎么让子线程去做主线程的事儿呢,我们只需要把主线程的方法传递给子线程就行了,那么传递方法就 ...

  5. C#子线程执行完后,调用主线程的方法

    private delegate void CheckVersionNumber_CallBack(string str);//定义一个为委托 用于 检测版本 //检测版本private void m ...

  6. C#子线程执行完后通知主线程(转)

    其实这个比较简单,子线程怎么通知主线程,就是让子线程做完了自己的事儿就去干主线程的转回去干主线程的事儿.  那么怎么让子线程去做主线程的事儿呢,我们只需要把主线程的方法传递给子线程就行了,那么传递方法 ...

  7. 在C#主线程和子线程将数据传递给对方如何实现

    在C#中主线程和子线程怎样实现互相传递数据 老帅 在C#中创建线程Thread时,能够有多种方法,而主线程和子线程之间又怎样实现互相传递数据,每种创建方法传递參数的效果是不同的,逐一看一下:  一.不 ...

  8. android 通过子线程跳转activity并传递内容

    android 子线程中不能够更新ui已经根深蒂固在我的脑海里,当时也就理所当然的觉得子线程中也是不能够进行界面的跳转的,可是在后来的学习中,发现居然是能够通过子线程来进行activity的跳转时,立 ...

  9. python3 结束子线程

    最近公司内部网络经常出问题,奇慢无比,导致人脸检测程序在下载图片时经常卡住,为了不影响数据的核对, 决定在网络不佳图片下载超时后放弃下载,继续执行后续程序. 于是整理出解决思路如下: 1.在线程中完成 ...

随机推荐

  1. socket握手SYN和ACK理解

    ACK 英文缩写: ACK (ACKnowledge Character) 中文译名: 确认字符 分类: 传输与接入 解释: 在数据通信传输中,接收站发给发送站的一种传输控制字符.它表示确认发来的数据 ...

  2. js使用心得——避免全局变量冲突的小技巧

    在写js代码的时候,经常会因为这样或者那样的原因用到全局变量,如果全局变量只在一个js里使用,那就没问题,但如果变量在不同的js文件里出现,这时隐藏的问题就会开始暴露,也许你能很快修复出现的BUG,又 ...

  3. StartDT_AI_Lab | 开启“数据+算法”定义的新世界

    继「数据中台技术汇」栏目推出以来,获得了不少技术极客的喜爱.作为AI驱动的数据中台创导者,深度关注核心算法技术的自研创新.融合探索,故推出全新AI算法栏目「StartDT_AI_Lab」,主要介绍算法 ...

  4. 提前窥测奥斯卡颁奖信封中的谜底  ——Rothschild预测2014奥斯卡花落谁家

     --Rothschild预测2014奥斯卡花落谁家" title="提前窥测奥斯卡颁奖信封中的谜底  --Rothschild预测2014奥斯卡花落谁家"> 编者 ...

  5. HTML的img标签:alt属性和title属性

    当浏览器卖主扭曲了标准并且自顾自的不按规则去做一些事,他们可能会造成一些问题,或者至少产生了混淆.例子之一就是一些浏览器处理alt属性(一般会被错误的称作alt标签)的方式,比如拥有大量用户的Wind ...

  6. 吴裕雄--天生自然Android开发学习:1.2 开发环境搭建

    现在主流的Android开发环境有: ①Eclipse + ADT + SDK ②Android Studio + SDK ③IntelliJ IDEA + SDK 现在国内大部分开发人员还是使用的E ...

  7. django自带数据库sqlite

    python manage.py makemigrations # 记录关于models.py的所有改动,但是还没有作用的数据库文件中 python manage.py migrate # 把mode ...

  8. Mac使用sublime text3的快捷键

    符号说明⌘:command⌃:control⌥:option⇧:shift↩:enter⌫:delete 打开/关闭/前往⌘⇧N 打开一个新的sublime窗口⌘N 新建文件⌘⇧W 关闭sublime ...

  9. Linux(Centos7.X ) 配置Java 环境变量

    前提条件:上传Jdk 文件到Linux服务器上. tar -zxvf jdk-8u111-linux-x64.tar.gz 修改 /etc/profile 在打开的文件末尾添加如下内容: export ...

  10. CF-1114C-Trailing Loves (or L'oeufs?)

    题意: 输入n和m,求n!转换成m进制之后末尾有多少个0: 思路: 转换一下题意就可以看成,将n表示成x * (m ^ y),求y的最大值.^表示次方而不是异或: 这就比较好想了,将m分解质因数,对于 ...