wd and cc

-- Good good study, day day up!

Learning Python Coroutine

#Python #Coroutine

看了一个视频 OSB 2015 - How Do Python Coroutines Work?,从头开始讲 coroutine 是怎么抽象出来的,感觉好厉害。自己写了一点程序学习了一下。之前写的关于 coroutine 的帖子。

先准备一个 server.py ,可以接受客户端请求。要注意的是要使用 Threading ,或者 fork 的 server,要不服务端执行并不支持并发,需要处理完一个才能处理下一个,这样会发现虽然客户端那边请求是并发的,但是返回结果的时候是顺序的。

 1import socketserver
 2from time import sleep
 3
 4HOST = '127.0.0.1'
 5PORT = 2045
 6
 7class MyTCPHandler(socketserver.BaseRequestHandler):
 8    def handle(self):
 9        data = self.request.recv(1024)
10        sleep(1)
11        self.request.sendall('{} ok'.format(data.decode()).encode())
12
13
14def run():
15    server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
16    server.serve_forever()
17
18if __name__ == '__main__':
19    run()

然后是 client.py ,可以比较下里面 sync_callasync_call 的区别。

 1import socket
 2from time import time
 3import asyncio
 4
 5HOST = '127.0.0.1'
 6PORT = 2045
 7
 8start = time()
 9
10def get(path):
11    print('get {}'.format(path))
12    s = socket.socket()
13    s.connect((HOST, PORT))
14
15    s.sendall(path.encode())
16
17    chunk = s.recv(100)
18    print('get {}'.format(chunk.decode()))
19
20def sync_call():
21    get('/bar')
22    get('/foo')
23
24
25async def async_get(path):
26    print('get {}'.format(path))
27    reader, writer = await asyncio.open_connection(HOST, PORT)
28
29    writer.write(path.encode())
30    await writer.drain()
31
32    chunk = await reader.read(100)
33    print('get {}'.format(chunk.decode()))
34
35def async_call():
36    loop = asyncio.get_event_loop()
37
38    t1 = loop.create_task(async_get('/bar'))
39    t2 = loop.create_task(async_get('/foo'))
40
41    loop.run_until_complete(asyncio.gather(t1, t2))
42
43if __name__ == "__main__":
44    #sync_call()
45    async_call()
46    print('total {:.2f} seconds'.format(time() - start))

这里网络请求也需要使用非阻塞的库。创建 task 实际有挺多方法的,这里随便用了一个。

comments powered by Disqus