import socket from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE selector = DefaultSelector() stopped = False r0 = request(0, "/1") r1 = request(1, "/2") t_list = [r0 ,r1] r0.send(None) r1.send(None) def request(index, address): sock = socket() sock.connect(address) def on_read(): print(sock.recv()) t_list[index].send(None) selector.register(sock.fileno(), EVENT_READ, on_read) yield # 遇到io,将运行的权利交出去 selector.unregister(sock.fileno()) print(‘完成了‘) while True: events = selector.select() for event_key, event_mask in events: callback = event_key.data callback()
代码分析:
1.程序一开始就注册里两个生成器,r0和r1,并且保存在t_list 这个数组里面
并且进行了第一次执行
2.request:
首先定义了一个socket, 并且连接到传递进来的address
并且注册了一个读的事件的回调,并且yield出来,跳出生成器,等待下一次执行
既然已经yield出来,那么生成器下一次执行怎么办,到底需要怎么执行
所以这里的回调就有些意思了,当数据就绪之后,会执行回调
t_list[index].send(None) ,
重新获取到本身这个生成器的引用,然后重新执行一次
等于是当自己的数据已经就绪好了,就会执行自己的回调,自己的回调就是重新调用一下自己,继续激活自己本身这个生成器
3. events = selector.select()当收到读的事件,然后遍历所有的事件,提取出它的回调,
callback = event_key.data callback() 并且执行回调
所以协程的基本原理就是:在遇到 io、阻塞的时候,将运行的权利交出去(例如上面的yield),同时注册唤醒自己的回调;
当阻塞事件完成的时候,通过一个回调来唤醒程序继续往下走,并且返回io事件的值。这句话记下来,考试要考!!!!
原文:https://www.cnblogs.com/wilken/p/14233000.html