六十四 asyncio
asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。
asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
用asyncio实现Hello world代码如下:
import asyncio @asyncio.coroutine
def hello():
print("Hello world!")
# 异步调用asyncio.sleep():
r = yield from asyncio.sleep()
print("Hello again!") # 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()
@asyncio.coroutine把一个generator标记为coroutine类型,然后,我们就把这个coroutine扔到EventLoop中执行。
hello()会首先打印出Hello world!,然后,yield from语法可以让我们方便地调用另一个generator。由于asyncio.sleep()也是一个coroutine,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,线程就可以从yield from拿到返回值(此处是None),然后接着执行下一行语句。
把asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行。
我们用Task封装两个coroutine试试:
import threading
import asyncio @asyncio.coroutine
def hello():
print('Hello world! (%s)' % threading.currentThread())
yield from asyncio.sleep()
print('Hello again! (%s)' % threading.currentThread()) loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
观察执行过程: Hello world! (<_MainThread(MainThread, started )>)
Hello world! (<_MainThread(MainThread, started )>)
(暂停约1秒)
Hello again! (<_MainThread(MainThread, started )>)
Hello again! (<_MainThread(MainThread, started )>)
由打印的当前线程名称可以看出,两个coroutine是由同一个线程并发执行的。
如果把asyncio.sleep()换成真正的IO操作,则多个coroutine就可以由一个线程并发执行。
我们用asyncio的异步网络连接来获取sina、sohu和163的网站首页:
import asyncio @asyncio.coroutine
def wget(host):
print('wget %s...' % host)
connect = asyncio.open_connection(host, )
reader, writer = yield from connect
header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host
writer.write(header.encode('utf-8'))
yield from writer.drain()
while True:
line = yield from reader.readline()
if line == b'\r\n':
break
print('%s header > %s' % (host, line.decode('utf-8').rstrip()))
# Ignore the body, close the socket
writer.close() loop = asyncio.get_event_loop()
tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
执行结果如下: wget www.sohu.com...
wget www.sina.com.cn...
wget www..com...
(等待一段时间)
(打印出sohu的header)
www.sohu.com header > HTTP/1.1 OK
www.sohu.com header > Content-Type: text/html
...
(打印出sina的header)
www.sina.com.cn header > HTTP/1.1 OK
www.sina.com.cn header > Date: Wed, May :: GMT
...
(打印出163的header)
www..com header > HTTP/1.0 Moved Temporarily
www..com header > Server: Cdn Cache Server V2.
... 可见3个连接由一个线程通过coroutine并发完成。
小结 asyncio提供了完善的异步IO支持; 异步操作需要在coroutine中通过yield from完成;
六十四 asyncio的更多相关文章
- 第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理
第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理 1.映射(mapping)介绍 映射:创建索引的时候,可以预先定义字 ...
- Gradle 1.12用户指南翻译——第六十四章. 发布到Ivy(新)
其他章节的翻译请参见:http://blog.csdn.net/column/details/gradle-translation.html翻译项目请关注Github上的地址:https://gith ...
- “全栈2019”Java第六十四章:接口与静态方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3
孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十天. 今天继续学习mongoDB的简单操作, ...
- SpringBoot进阶教程(六十四)注解大全
在Spring1.x时代,还没出现注解,需要大量xml配置文件并在内部编写大量bean标签.Java5推出新特性annotation,为spring的更新奠定了基础.从Spring 2.X开始spri ...
- OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- 第六十四天 JS基础操作
一.分支结构 1.if语句 if基础语句 if(条件表达式){ 代码块: } // 当条件表达式结果为true,会执行代码块:反之不执行 // 条件表达式可以为普通表达式 // 0.undefined ...
- 【WPF学习】第六十四章 构建基本的用户控件
创建一个简单用户控件是开始自定义控件的好方法.本章主要介绍创建一个基本的颜色拾取器.接下来分析如何将这个控件分解成功能更强大的基于模板的控件. 创建基本的颜色拾取器很容易.然而,创建自定义颜色拾取器仍 ...
- python六十四课——高阶函数练习题(三)
案例五:求两个列表元素的和,返回新列表lt1 = [1,2,3,4]lt2 = [5,6]效果:[6,8,10,12] lt1=[1,2,3,4] lt2=[5,6] print(list(map(l ...
随机推荐
- 关于jmf不能播放mp3的问题解决
想写个JAVA的MP3音乐管理器,使用JMF插件,但发现运行时总报一个异常: Unable to handle format: mpeglayer3, 44100.0 Hz, 16-bit, Ster ...
- MyBatis框架的使用及源码分析(十三) ResultSetHandler
在PreparedStatementHandler中的query()方法中,用ResultSetHandler来完成结果集的映射. public <E> List<E> que ...
- 省队集训 Day3 杨北大
[题目大意] 给出平面上$n$个点$(x_i, y_i)$,请选择一个不在这$n$个点之内的点$(X, Y)$,定义$(X, Y)$的价值为往上下左右四个方向射出去直线,经过$n$个点中的数量的最小值 ...
- 【转载】VS2013安装需要IE10
因为需要移动办公,需要给笔记本搭建编程环境.安装VS2013时遇到了小麻烦,提示我,需要安装IE10. 然后我很听话的按照提供的超链接,到了官网,下载了最新的IE11,然后安装,结果告诉我下载的IE版 ...
- Vue 使用中的小技巧(山东数漫江湖)
在vue的使用过程中会遇到各种场景,当普通使用时觉得没什么,但是或许优化一下可以更高效更优美的进行开发.下面有一些我在日常开发的时候用到的小技巧,在下将不定期更新~ 1. 多图表resize事件去中心 ...
- 【转】ps命令详解
原文地址:http://apps.hi.baidu.com/share/detail/32573968 有 时候系统管理员可能只关心现在系统中运行着哪些程序,而不想知道有哪些进程在运行.由于一个应用程 ...
- aircrack加reaver破解带有wps的wifi
最近心血来潮,想把小区里的无线信号测试个遍.基于目前大多数路由器都支持wps,想必各位基友们都知道aircrack和reaver这 两个工具,实属破解pin码,杀人越货,居家旅行之必备良药.像以前跑r ...
- vue基本介绍
https://cn.vuejs.org/v2/guide/ Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上 ...
- linux命令行todo列表管理工具Taskwarrior介绍
Taskwarrior 是一款在命令行下使用的TODO列表管理工具,或者说任务管理工具,灵活,快速,高效. 安装 在ubuntu 14.04 中,可从官方仓库安装task软件包 sudo apt-ge ...
- Yii 1.1.17 三、数据库连接、定义模型、数据查询、验证登录、SESSION使用与URL生成
一.数据库连接 1.配置连接参数 在database.php里面开启: 'db' => array( 'connectionString' => 'mysql:host=127.0.0.1 ...