这里的异步编程基于python3.4和python3.5

1、一些重要的概念理解

(1)循环消息队列:          

  • 异步IO采用消息循环的模式,重复“读取消息—处理消息”的过程
  • 消息模型解决等待IO操作的问题: 
  • 程序发出IO请求,直接结束本轮消息处理,进入下一轮消息的处理
  • 当IO操作完成守,将收到一条IO完成的消息,处理该消息时获取IO操作的结果
  • 在IO操作的这段时间里,异步模型可以循环处理其他操作,而且没有线程切换的消耗,同时处理多个IO请求,适用于大多数IO密集型的应用程序
  • 总结; "异步IO模型"需要一个消息循环,在消息循环中,主线程不断地重复“读取消息-处理消息”这一过程。
  • (2)协程——coroutine
  • 协程,又称微线程,纤程。英文名Coroutine。协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。
  •        协程调用与函数调用的区别:
  • 即函数)内部可中断,然后转而执行别的子程序(另一个函数),在适当的时候再返回                          来接着执行。
                           协程针对的是一个线程中的函数调用之间,所以没有线程切换,是在一个线程中轮流执行和终端多个函数而已,所                          以效率较高,而且不需要锁机制(只有一个线程执行)
                           需要注意的是,子程序内部中断的不是函数调用,而是被调用函数中断(一般来说可能是一条执行命令需要很长时                          间等待结果返回,比如常见的IO操作),转而去执行另一个函数(不是调用另一个函数),类似两个函数轮流执                            行,没有发生函数调用。
  •        函数调用:程序执行中,函数调用是通过函数栈实现,因为栈FILO的特点,通常函数调用过程都是:A调用B,B在执行过程中                        又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。子程序(函数)调用总是一个入口,一次返                              回,调用顺序是明确的。而协程的调用和子程序不同
  • 总结:协程的本质就是一个子程序,即一个使用async关键字定义的函数(在python3.4中使用的是@async.corontine修饰的函                数),它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用
  • (3)、事件循环
  •       python异步IO的核心就在于事件循环,事件循环是一个无限的循环,程序开启一个无限的循环,程序员会把一些协程函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。即协程函数不是自己调用的,而是通过“事件循环”去掉用的。
  •       操作如下:
  • loop = asyncio.get_event_loop() #获取“事件循环”对象
  • loop.run_until_complete(hello()) #通过事件循环,去调用协程函数
  • loop.close()
  • (4)、任务task
  • 协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。即多个coroutine函数可以封装成一组Task然后并发执行,所谓task对象是Future类的子类。保存了协程运行后的状态,用于未来获取协程的结果。任务一般是有多个协程函数的时候,将他们绑定到一个任务组上,可以如下操作:
loop = asyncio.get_event_loop()
tasks = [hello(), hello1(),hello2(),hello3()]  #多个协程函数绑定到一个任务上面,记住多个任务需要将任务写成                                                      列表的形式     
loop.run_until_complete(asyncio.wait(tasks))         #当任务是列表的时候,必须使用asyncio.wait(t)的形式才行
loop.close()
  • loop.run_until_complete(hello()) #程序也会自动将hello封装成一个task任务,若函数有参数,一定要传入参数哦
  • 下面是几种创建任务的方法:
  • 方法1:通过loop.create_task()创建任务
• =[loop.create_task(number_sub( 
    10))] #因为是列表的形式,所以下面必须要用asyncio.wait(t)作为参数,否则会报错 
     loop.run_until_complete(asyncio.wait(t)) 
     loop.close()

  • 与下面的等价
=loop.create_task(number_sub( 
    10)) #因为不是列表的形式,所以不需要 
    asyncio.wait,而直接将t作为参数,否则会报错 
     loop.close()

方法2:通过 asyncio.ensure_future()创建任务

=[asyncio.ensure_future(number_sub( 
    10))] 
     #因为是列表的形式,所以下面必须要用asyncio.wait(t)作为参数,否则会报错 
     loop.close()  
=asyncio.ensure_future(number_sub( 
    10)) 
     #因为不是列表的形式,所以不需要 
    asyncio.wait,而直接将t作为参数,否则会报错 
      loop.close()

方法3:一次将多个协程函数绑定到同一个任务——要写成任务列表的形式

#t=[asyncio.ensure_future(number_sub(10)),asyncio.ensure_future(character_list())] #方法一     
=[loop.create_task(number_sub( 
     10)),loop.create_task(character_list())] #方法二 
   =[number_sub( 
    10),character_list()] #方法三,这三种方法都可以 
     loop.run_until_complete(asyncio.wait(t)) #但因为是列表形式,所以要用wait   
     loop.close() 
=asyncio.gather(asyncio.ensure_future(number_sub( 
    5)), asyncio.ensure_future(character_list()))   
   print(t) 
  loop.run_until_complete(t) #通过asyncio的gather()方法将多个协程函数连接起来,而没有写成列表形式,故而不需要wait()    
   print(t)  
     loop.close()

  • task进一步了解:
  • task也是一个对象,我们还可以通过打印task,来来查看相关的一些状态信息,如下所示:
• =asyncio.get_event_loop() 
   =loop.create_task(number_sub( 
    10))    
   print(t) #执行之前的状态 
   loop.run_until_complete(t)    
   print(t) 
    loop.close() 
     <Task pending coro=<number_sub() running at f:\�о������꼶��\Tensorflow���ѧϰ\TensorFlowBoardʵ��\asyncio_3.4.py:3>> 
     it's 10   
     it's 9 
    it's 8   
     it's 7 
    it's 6  
     it's 5 
   it's 4 
    it's 3 
   it's 2   
     it's 1   
     <Task finished coro=<number_sub() done, defined at f:\�о������꼶��\Tensorflow���ѧϰ\TensorFlowBoardʵ��\asyncio_3.4.py:3> result=None>

  • task是Future的子类。isinstance(task, asyncio.Future)将会输出True。
  • 下面是整个程序的代码:
import    
@asyncio.coroutine #在python3.5里面,改为了async def number_sub(n): 
   def 
     number_sub(n):   
   while n 
    > 
    0:   
   print( 
    "it's  
    {0} 
    ".format(n))  
   yield 
    from asyncio.sleep( 
    1) 
    #asyncio.sleep()本身就是一个“异步协程函数” 当然这里可以是其他自定义的异步协程函数, 
   #这里仅仅是模拟一个耗时的异步过程 
   -= 
    1  #在python3.5里面,改为了await asyncio.sleep(1) 
   
@asyncio.coroutine  #在python3.5里面,改为了async def number_sub(n): 
   def 
     character_list():   
   =[ 
    'a', 
    'b', 
    'c', 
    'd', 
    'e', 
    'f', 
    'g'] 
    
   for i 
    in 
   print( 
    "it's  
    {0} 
    ".format(i)) 
    
   yield 
    from asyncio.sleep( 
    1) 
     #在python3.5里面,改为了await asyncio.sleep(1)    
   =asyncio.gather(asyncio.ensure_future(number_sub( 
    5)), asyncio.ensure_future(character_list())) 
    loop.run_until_complete(t)  
     loop.close()