Python中asyncio模块的深入讲解

作者:且听风吟 时间:2022-05-18 22:33:53 

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然后并发执行。

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

来源:https://www.lylinux.net/article/2019/6/9/57.html

标签:asyncio,python
0
投稿

猜你喜欢

  • Python检测一个对象是否为字符串类的方法

    2022-11-02 15:25:24
  • PHP的PDO大对象(LOBs)

    2023-06-07 06:45:36
  • python爬虫之Appium爬取手机App数据及模拟用户手势

    2023-12-28 00:10:46
  • python 弹窗提示警告框MessageBox的实例

    2023-11-12 01:07:17
  • asp动态页面防采集的新方法

    2011-02-26 10:44:00
  • asp中最新新闻显示new图片的实现代码

    2012-11-30 20:31:42
  • pytorch常用数据类型所占字节数对照表一览

    2021-07-25 15:26:29
  • python实现canny边缘检测

    2022-03-05 00:24:08
  • 解决Pytorch在测试与训练过程中的验证结果不一致问题

    2022-08-18 03:50:13
  • Pycharm配置远程调试的方法步骤

    2021-03-13 00:45:38
  • 当视觉设计师遇上产品经理、开发工程师…[译]

    2010-01-17 10:18:00
  • ASP进阶学习之认识数学函数

    2007-10-08 13:15:00
  • CSS文字排版终极指南

    2010-01-19 10:30:00
  • Python清空文件并替换内容的实例

    2023-03-22 04:09:43
  • php中json_encode不兼容JSON_UNESCAPED_UNICODE的解决方案

    2023-09-27 17:22:32
  • Python matplotlib超详细教程实现图形绘制

    2023-04-20 06:37:53
  • Python如何telnet到网络设备

    2023-11-20 09:47:45
  • 联动选择菜单(二级联动菜单 三 级联动菜单)

    2023-06-26 22:37:55
  • python http接口自动化脚本详解

    2022-09-01 05:24:30
  • python进行OpenCV实战之画图(直线、矩形、圆形)

    2022-05-30 06:36:05
  • asp之家 网络编程 m.aspxhome.com