在学习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. Gson、jackson 序列化,反序列化(单个、集合)

    实体类: package com.nf.redisDemo1.entity; public class News { private long id; private String title; pr ...

  2. python3下scrapy爬虫(第十三卷:scrapy+scrapy_redis+scrapyd打造分布式爬虫之配置)

    之前我们的爬虫都是单机爬取,也是单机维护REQUEST队列, 看一下单机的流程图: 一台主机控制一个队列,现在我要把它放在多机执行,会产生一个事情就是做重复的爬取,毫无意义,所以分布式爬虫的第一个难点 ...

  3. COMET探索系列一【COMET实践笔记】

    这几天在给公司的一个点对点聊天系统升级,之前只是使用简单的ajax轮询方式实现,每5秒钟取一次数据,延时太长,用户体验不是很好,因此打算采用服务器推送技术,故此整理了以下文档,将自己找到的一些资料及心 ...

  4. ROC曲线、KS曲线

    一.ROC曲线 ROC曲线由混淆矩阵为基础数据生成. 纵坐标:真阳性比率TPR,预测为正占真正为正的比例. 横坐标:假阳性比率FPR,预测为正占真正为负的比例. 除了roc曲线的纵横坐标外,还有一个准 ...

  5. Java开发面试常见问题合集

    次面试事故 面试官:你看过哪些源码?我:都挺熟悉的面试官:对hashMap了解程度怎么样?面试官:那你能讲讲 HashMap的实现原理吗?面试官:HashMap什么时候会进行 rehash?面试官:结 ...

  6. Python自动化之数据驱动(转载下自己的日常练习笔记)

    一.execl数据驱动 1.xlutils简要说明 导包:pip3 install xlutils 注意⚠️:xlutils在介些Execl文件的时候,只识别.xls后缀的文件,如果是.xlsx后缀的 ...

  7. [洛谷P4782] [模板] 2-SAT 问题

    NOIp后第一篇题解. NOIp我考的很凉啊...... 题目传送门 之前讲过怎么判断2-SAT是否存在解. 至于如何构造一组解: 我们想到对tarjan缩点后的图进行拓扑排序. 那么对于代表0状态的 ...

  8. Docker跨主机容器之间的通信macvlan

    找两台测试机: [root@docker1 centos_zabbix]# docker network ls NETWORK ID NAME DRIVER SCOPE 19ac9a55bedb br ...

  9. mysql获取按日期排序获取最新的记录

    今天让一个数据查询难了.主要是对group by 理解的不够深入.才出现这样的情况 这种需求,我想很多人都遇到过.下面是我模拟我的内容表 我现在需要取出每个分类中最新的内容 select * from ...

  10. php数据库连接和mysql语句使用

    从简单的登录页开始学习. 前提:已经有一个html+css+js的静态网站 登录: php连接数据库,读取数据. <?php $username = root; $userpass = shao ...