Python中asyncio模块的深入讲解

  


  

  

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模块的深入讲解