Learning Python Coroutine
看了一个视频 OSB 2015 - How Do Python Coroutines Work?,从头开始讲 coroutine 是怎么抽象出来的,感觉好厉害。自己写了一点程序学习了一下。之前写的关于 coroutine 的帖子。
先准备一个 server.py
,可以接受客户端请求。要注意的是要使用 Threading
,或者 fork
的 server,要不服务端执行并不支持并发,需要处理完一个才能处理下一个,这样会发现虽然客户端那边请求是并发的,但是返回结果的时候是顺序的。
import socketserver
from time import sleep
HOST = '127.0.0.1'
PORT = 2045
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024)
sleep(1)
self.request.sendall('{} ok'.format(data.decode()).encode())
def run():
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
if __name__ == '__main__':
run()
然后是 client.py
,可以比较下里面 sync_call
和 async_call
的区别。
import socket
from time import time
import asyncio
HOST = '127.0.0.1'
PORT = 2045
start = time()
def get(path):
print('get {}'.format(path))
s = socket.socket()
s.connect((HOST, PORT))
s.sendall(path.encode())
chunk = s.recv(100)
print('get {}'.format(chunk.decode()))
def sync_call():
get('/bar')
get('/foo')
async def async_get(path):
print('get {}'.format(path))
reader, writer = await asyncio.open_connection(HOST, PORT)
writer.write(path.encode())
await writer.drain()
chunk = await reader.read(100)
print('get {}'.format(chunk.decode()))
def async_call():
loop = asyncio.get_event_loop()
t1 = loop.create_task(async_get('/bar'))
t2 = loop.create_task(async_get('/foo'))
loop.run_until_complete(asyncio.gather(t1, t2))
if __name__ == "__main__":
#sync_call()
async_call()
print('total {:.2f} seconds'.format(time() - start))
这里网络请求也需要使用非阻塞的库。创建 task 实际有挺多方法的,这里随便用了一个。