Python中asyncio模块内置了对异步IO的支持,用于处理异步IO;是Python 3.4版本引入的标准库。
asyncio的编程模型就是一个消息循环。我们从asyncio块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
#?usr/bin/env python3 # - * -编码:utf - 8 - * # @Time: 2019/1/9 11:23 # @Author:箭和子弹 # @FileName: test.py # @Software: PyCharm # @Blog: https://blog.csdn.net/qq_41800366 进口asyncio @asyncio.coroutine def hello (): 打印(“Hello world !”) #异步调用asyncio.sleep (2): 产量从asyncio.sleep (2) 打印(“你好!”) #获取EventLoop: 循环=asyncio.get_event_loop () #执行协同程序 loop.run_until_complete (hello ()) loop.close ()
@asyncio。协同程序把一个发电机标记为协同程序类型,然后,我们就把这个协同程序扔到EventLoop中执行。
hello()会首先打印出hello world !,然后,收益率从语法可以让我们方便地调用另一个发电机。由于asyncio.sleep()也是一个协同程序,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,线程就可以从收益率从拿到返回值(此处是没有),然后接着执行下一行语句。
把asyncio.sleep(2)看成是一个耗时2秒的IO操作(比如读取大文件),在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的协同程序了,因此可以实现并发执行。
我们用任务封装两个协同程序试试:
进口线程 进口asyncio @asyncio.coroutine def hello (): 打印(“Hello world !”(% s) % threading.currentThread ()) 产量从asyncio.sleep (2) 打印('你好!(% s) % threading.currentThread ()) 循环=asyncio.get_event_loop () 任务=(hello (), hello ()) loop.run_until_complete (asyncio.wait(任务) loop.close ()
观察执行过程:
Hello world !(& lt; _MainThread (MainThread,开始140735195337472)祝辞)
引用>
你好世界!(& lt; _MainThread (MainThread,开始140735195337472)祝辞)
(暂停约2秒)
你好了!(& lt; _MainThread (MainThread,开始140735195337472)祝辞)
你好了!(& lt; _MainThread (MainThread,开始140735195337472)祝辞)
由打印的当前线程名称可以看的出,两个协同程序是由同一个线程并发执行的。
如果把asyncio.sleep()换成真正的IO操作,则多个协同程序就可以由一个线程并发执行。
我们用asyncio的异步网络连接来获取新浪,搜狐和163的网站首页:
进口asyncio @asyncio.coroutine def wget(主持人): 打印(wget %年代…' %主机) 连接=asyncio。open_connection(主机,80)#创建连接 读者,作者从连接=产量 头=' GET/HTTP/1.0 \ r \ nHost: % s \ r \ n \ r \ n ' %主机 writer.write (header.encode (utf - 8)) 产量从writer.drain () 而真正的: 从reader.readline=产量() 如果行==b“\ r \ n”: 打破 打印(' % s头比;% s ' %(主机、line.decode (utf - 8) .rstrip ())) #忽略了身体,关闭套接字 writer.close () 循环=asyncio.get_event_loop () 任务=[wget的主机(主机)[' www.sina.com.cn ', ' www.sohu.com ', ' www.163.com ']] loop.run_until_complete (asyncio.wait(任务) loop.close ()执行结果如下:
wget www.sohu.com…
引用>
wget www.sina.com.cn…
wget www.163.com…
(等待一段时间)
(打印出搜狐的头)
www.sohu.com头比;HTTP/1.1 200 OK
www.sohu.com头比;的content - type: text/html
…
(打印出新浪的标题)
www.sina.com.cn头比;HTTP/1.1 200 OK
www.sina.com.cn头比;日期:2015年5月20日结婚04:56:33格林尼治时间
…
(打印出163的头)
www.163.com头比;HTTP/1.0 302移动暂时
www.163.com头比;服务器:Cdn缓存服务器V2.0
…
可见3个连接由一个线程通过协同程序并发完成。
asyncio提供了完善的异步IO支持,
异步操作需要在协同程序中通过收益率从完成;
Python中asyncio模块的深入讲解