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 相关文章推荐
django模型中的字段和model名显示为中文小技巧分享
Nov 18 Python
介绍Python中的一些高级编程技巧
Apr 02 Python
Python编程实战之Oracle数据库操作示例
Jun 21 Python
Python从ZabbixAPI获取信息及实现Zabbix-API 监控的方法
Sep 17 Python
Python 文本文件内容批量抽取实例
Dec 10 Python
Python多进程fork()函数详解
Feb 22 Python
numpy中的ndarray方法和属性详解
May 27 Python
pandas的qcut()方法详解
Jul 06 Python
python web框架中实现原生分页
Sep 08 Python
Python实现屏幕录制功能的代码
Mar 02 Python
python数据可视化JupyterLab实用扩展程序Mito
Nov 20 Python
Python自动操作神器PyAutoGUI的使用教程
Jun 16 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
Sony CFR 320 修复改造
2020/03/14 无线电
PHP如何抛出异常处理错误
2011/03/02 PHP
php实现的网络相册图片防盗链完美破解方法
2015/07/01 PHP
PHP ob缓存以及ob函数原理实例解析
2020/11/13 PHP
另类调用flash无须激活的方法
2006/12/27 Javascript
Document 对象的常用方法
2009/07/31 Javascript
jQuery 处理表单元素的代码
2010/02/15 Javascript
js 关键词高亮(根据ID/tag高亮关键字)案例介绍
2013/01/21 Javascript
js跨浏览器实现将字符串转化为xml对象的方法
2013/09/25 Javascript
利用JS进行图片的切换即特效展示图片
2013/12/03 Javascript
javascript 寻找错误方法整理
2014/06/15 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
2015/02/03 Javascript
Java框架SSH结合Easyui控件实现省市县三级联动示例解析
2016/06/12 Javascript
js中使用使用原型(prototype)定义方法的好处详解
2016/07/04 Javascript
select隐藏选中值对应的id,显示其它id的简单实现方法
2016/08/25 Javascript
详解js中Json的语法与格式
2016/11/22 Javascript
node.js版本管理工具n无效的原理和解决方法
2016/11/24 Javascript
js 数字、字符串、布尔值的转换方法(必看)
2017/04/07 Javascript
微信小程序实现图片放大预览功能
2020/10/22 Javascript
Node.js net模块功能及事件监听用法分析
2019/01/05 Javascript
JavaScript设计模式之责任链模式实例分析
2019/01/16 Javascript
解决layer.msg 不居中 ifram中的问题
2019/09/05 Javascript
python 识别图片中的文字信息方法
2018/05/10 Python
Python装饰器模式定义与用法分析
2018/08/06 Python
Python之lambda匿名函数及map和filter的用法
2019/03/05 Python
numpy中的meshgrid函数的使用
2019/07/31 Python
Python小白不正确的使用类变量实例
2020/05/29 Python
python实现简单的tcp 文件下载
2020/09/16 Python
美国汽配连锁巨头Pep Boys官网:轮胎更换、汽车维修服务和汽车零部件
2017/01/14 全球购物
怎样写留学自荐信
2013/11/11 职场文书
办公室前台的岗位职责
2013/12/20 职场文书
秋季开学典礼主持词
2014/03/19 职场文书
环保标语口号
2014/06/13 职场文书
发布会邀请函
2015/01/31 职场文书
幼儿园安全工作总结2015
2015/04/20 职场文书
css背景和边框标签实例详解
2021/05/21 HTML / CSS