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中的lambda表达式的用法
Aug 28 Python
python决策树之CART分类回归树详解
Dec 20 Python
Python实现的视频播放器功能完整示例
Feb 01 Python
django js实现部分页面刷新的示例代码
May 28 Python
解决Pycharm下面出现No R interpreter defined的问题
Oct 29 Python
python实现朴素贝叶斯算法
Nov 19 Python
pybind11在Windows下的使用教程
Jul 04 Python
python自动识别文本编码格式代码
Dec 26 Python
关于tensorflow的几种参数初始化方法小结
Jan 04 Python
pytorch实现mnist数据集的图像可视化及保存
Jan 14 Python
Python应用实现双指数函数及拟合代码实例
Jun 19 Python
利用Python将图片中扭曲矩形的复原
Sep 07 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
PHP 下载文件时自动添加bom头的方法实例
2014/01/10 PHP
Yii操作数据库的3种方法
2014/03/11 PHP
示例详解Laravel重置密码代码重构
2016/08/10 PHP
php版微信js-sdk支付接口类用法示例
2016/10/12 PHP
PHP Post获取不到非表单数据的问题解决办法
2018/02/27 PHP
理解javascript中的回调函数(callback)
2014/09/02 Javascript
javascript常用经典算法实例详解
2015/11/25 Javascript
JS跨域请求外部服务器的资源
2017/02/06 Javascript
深入浅析JavaScript中的RegExp对象
2017/09/18 Javascript
node内置调试方法总结
2018/02/22 Javascript
Angular2进阶之如何避免Dom误区
2018/04/02 Javascript
下载给定网页上图片的方法
2014/02/18 Python
使用Nginx+uWsgi实现Python的Django框架站点动静分离
2016/03/21 Python
Python 类与元类的深度挖掘 I【经验】
2016/05/06 Python
python简单图片操作:打开\显示\保存图像方法介绍
2017/11/23 Python
django 将model转换为字典的方法示例
2018/10/16 Python
python正则表达式匹配[]中间为任意字符的实例
2018/12/25 Python
使用Python3内置文档高效学习以及官方中文文档
2019/05/19 Python
如何不用安装python就能在.NET里调用Python库
2019/07/12 Python
python list数据等间隔抽取并新建list存储的例子
2019/11/27 Python
Python利用逻辑回归模型解决MNIST手写数字识别问题详解
2020/01/14 Python
HTML5 本地存储之如果没有数据库究竟会怎样
2013/04/25 HTML / CSS
HTML5 视频播放(video),JavaScript控制视频的实例代码
2018/10/08 HTML / CSS
医院后勤自我鉴定
2013/10/13 职场文书
《姥姥的剪纸》教学反思
2014/02/25 职场文书
2014婚礼司仪主持词
2014/03/14 职场文书
伊索寓言教学反思
2014/05/01 职场文书
市场营销战略计划书
2014/05/06 职场文书
药店促销活动总结
2014/07/10 职场文书
大二学生自我检讨书
2014/10/23 职场文书
临时用工协议书范本
2014/10/29 职场文书
行政前台岗位职责
2015/04/16 职场文书
学校捐书活动总结
2015/05/08 职场文书
幼儿园教研工作总结2015
2015/05/12 职场文书
关于社会实践的心得体会(2016最新版)
2016/01/25 职场文书
使用python求解迷宫问题的三种实现方法
2022/03/17 Python