使用协程建立自己的异步非阻塞模型
接下来例子中,将使用纯粹的Python编码搭建一个异步模型,相当于自己构建的一个asyncio模块,这也许能对asyncio模块底层实现的理解有更大的帮助。主要参考为文末的链接,以及自己的补充理解。
完整代码
1 #!/usr/bin/python 2 # ============================================================= 3 # File Name: async_base.py 4 # Author: LI Ke 5 # Created Time: 1/29/2018 09:18:50 6 # ============================================================= 7 8 9 import types 10 import time 11 12 13 @types.coroutine 14 def switch(): 15 print('Switch: Start') 16 yield 17 print('Switch: Done') 18 19 async def coro_1(): 20 print('C1: Start') 21 await switch() 22 print('C1: Stop') 23 24 25 async def coro_2(): 26 print('C2: Start') 27 print('C2: 1') 28 print('C2: 2') 29 print('C2: 3') 30 print('C2: Stop') 31 32 c_1 = coro_1() 33 c_2 = coro_2() 34 35 try: 36 c_1.send(None) 37 except StopIteration: 38 pass 39 try: 40 c_2.send(None) 41 except StopIteration: 42 pass 43 try: 44 c_1.send(None) 45 except StopIteration: 46 pass 47 48 print('--------------------------------') 49 50 def run(coros): 51 coros = list(coros) 52 53 while coros: 54 # Duplicate list for iteration so we can remove from original list 55 for coro in list(coros): 56 try: 57 coro.send(None) 58 except StopIteration: 59 coros.remove(coro) 60 61 c_1 = coro_1() 62 c_2 = coro_2() 63 run([c_1, c_2]) 64 65 print('--------------------------------') 66 67 @types.coroutine 68 def action(t): 69 trace=[] 70 while True: 71 trace.append(time.time()) 72 if trace[-1] - trace[0] > t: 73 break # This break will end this function and raise a StopIteration 74 yield 75 76 async def coro_1(): 77 print('C1: Start') 78 await action(2) 79 print('C1: Stop') 80 81 82 async def coro_2(): 83 print('C2: Start') 84 await action(3) 85 print('C2: Stop') 86 87 def timeit(f): 88 def _wrapper(*args, **kwargs): 89 start = time.time() 90 re = f(*args, **kwargs) 91 end = time.time() 92 print('Time cost:', f.__name__, end-start) 93 return re 94 return _wrapper 95 96 c_1 = coro_1() 97 c_2 = coro_2() 98 timeit(run)([c_1]) 99 timeit(run)([c_2]) 100 101 print('--------------------------------') 102 103 c_1 = coro_1() 104 c_2 = coro_2() 105 timeit(run)([c_1, c_2])