Python中asyncio模块的深入讲解


Posted in Python onJune 10, 2019

1. 概述

Python中 asyncio 模块内置了对异步IO的支持,用于处理异步IO;是Python 3.4版本引入的标准库。

asyncio 的编程模型就是一个消息循环。我们从 asyncio 块中直接获取一个 EventLoop 的引用,然后把需要执行的协程扔到 EventLoop 中执行,就实现了异步IO。

2. 用asyncio实现Hello world

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2019/1/9 11:23
# @Author : Arrow and Bullet
# @FileName: test.py
# @Software: PyCharm
# @Blog :https://blog.csdn.net/qq_41800366
import asyncio

@asyncio.coroutine
def hello():
 print("Hello world!")
 # 异步调用asyncio.sleep(2): 
 yield from asyncio.sleep(2)
 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(2)看成是一个耗时2秒的IO操作(比如读取大文件),在此期间,主线程并未等待,而是去执行 EventLoop 中其他可以执行的 coroutine 了,因此可以实现并发执行。

我们用task封装两个coroutine试试:

import threading
import asyncio


@asyncio.coroutine
def hello():
 print('Hello world! (%s)' % threading.currentThread())
 yield from asyncio.sleep(2)
 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 140735195337472)>)
Hello world! (<_MainThread(MainThread, started 140735195337472)>)
(暂停约2秒)
Hello again! (<_MainThread(MainThread, started 140735195337472)>)
Hello again! (<_MainThread(MainThread, started 140735195337472)>)

由打印的当前线程名称可以看出,两个 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, 80) # 创建连接
 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.163.com...
(等待一段时间)
(打印出sohu的header)
www.sohu.com header > HTTP/1.1 200 OK
www.sohu.com header > Content-Type: text/html
...
(打印出sina的header)
www.sina.com.cn header > HTTP/1.1 200 OK
www.sina.com.cn header > Date: Wed, 20 May 2015 04:56:33 GMT
...
(打印出163的header)
www.163.com header > HTTP/1.0 302 Moved Temporarily
www.163.com header > Server: Cdn Cache Server V2.0
...

可见3个连接由一个线程通过coroutine并发完成。

3. 小结

asyncio提供了完善的异步IO支持;

异步操作需要在coroutine中通过yield from完成;

多个coroutine可以封装成一组Task然后并发执行。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python通过colorama模块在控制台输出彩色文字的方法
Mar 19 Python
通过5个知识点轻松搞定Python的作用域
Sep 09 Python
使用python遍历指定城市的一周气温
Mar 31 Python
用python实现对比两张图片的不同
Feb 05 Python
python实现媒体播放器功能
Feb 11 Python
Python3中正则模块re.compile、re.match及re.search函数用法详解
Jun 11 Python
Python二叉搜索树与双向链表转换算法示例
Mar 02 Python
Python中最好用的命令行参数解析工具(argparse)
Aug 23 Python
利用Tensorboard绘制网络识别准确率和loss曲线实例
Feb 15 Python
matplotlib 三维图表绘制方法简介
Sep 20 Python
Python pymysql模块安装并操作过程解析
Oct 13 Python
关于python爬虫应用urllib库作用分析
Sep 04 Python
Python中的asyncio代码详解
Jun 10 #Python
Django集成CAS单点登录的方法示例
Jun 10 #Python
详解Python中的测试工具
Jun 09 #Python
Python中函数参数匹配模型详解
Jun 09 #Python
Python程序包的构建和发布过程示例详解
Jun 09 #Python
Python面向对象之继承和多态用法分析
Jun 08 #Python
Python基本数据结构之字典类型dict用法分析
Jun 08 #Python
You might like
2020年4月放送!《Princess Connect Re:Dive》制作组 & 角色声优公开!
2020/03/06 日漫
PHP关于IE下的iframe跨域导致session丢失问题解决方法
2013/10/10 PHP
php实现检查文章是否被百度收录
2015/01/27 PHP
Avengerls vs KG BO3 第一场2.18
2021/03/10 DOTA
javascript学习笔记(三) String 字符串类型介绍
2012/06/19 Javascript
JavaScript取得鼠标绝对位置程序代码介绍
2012/09/16 Javascript
三种动态加载js的jquery实例代码另附去除js方法
2014/04/30 Javascript
如何用jQuery实现ASP.NET GridView折叠伸展效果
2015/09/26 Javascript
AngularJS 应用身份认证的技巧总结
2016/11/07 Javascript
JS 终止执行的实现方法
2016/11/24 Javascript
Json按某个键的值进行排序
2016/12/22 Javascript
js实现选项卡内容切换以及折叠和展开效果【推荐】
2017/01/08 Javascript
javascript笔记之匿名函数和闭包
2017/02/06 Javascript
教你使用vue-cli快速构建的小说阅读器
2019/05/13 Javascript
JQuery插件tablesorter表格排序实现过程解析
2020/05/28 jQuery
html+vue.js 实现漂亮分页功能可兼容IE
2020/11/07 Javascript
Python的string模块中的Template类字符串模板用法
2016/06/27 Python
Django如何实现内容缓存示例详解
2017/09/24 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
解决nohup重定向python输出到文件不成功的问题
2018/05/11 Python
Python一个简单的通信程序(客户端 服务器)
2019/03/06 Python
Linux下通过python获取本机ip方法示例
2019/09/06 Python
Python爬虫爬取Bilibili弹幕过程解析
2019/10/10 Python
Python HTTP下载文件并显示下载进度条功能的实现
2020/04/02 Python
Python爬虫实现百度翻译功能过程详解
2020/05/29 Python
HTML5样式控制示例代码
2013/11/27 HTML / CSS
营业员个人总结的自我评价
2013/10/25 职场文书
函授生自我鉴定
2014/03/25 职场文书
四风问题自我剖析材料
2014/10/07 职场文书
财务助理岗位职责范本
2014/10/09 职场文书
2015年公司后勤管理工作总结
2015/05/13 职场文书
2015中学学校工作总结
2015/07/20 职场文书
幼儿园奖惩制度范本
2015/08/05 职场文书
个人落户申请书怎么写?
2019/06/28 职场文书
小学生优秀作文范文(六篇)
2019/07/10 职场文书
Python游戏开发实例之graphics实现AI五子棋
2021/11/01 Python