python 异步与协程学习

参考:
深入理解Python异步编程
理解 Python asyncio

(1)异步非租塞
http://blog.csdn.net/yz764127031/article/details/72459158
以春运火车票为例,
异步—-你使用分流软件抢票,设置好时间类型,软件自动运行
非阻塞—-你不用等抢票结果,可以去做别的事
如何获得结果:
轮询—–每隔一段时间,你看一下抢到票没有
事件通知—-设置抢到票,邮件或者短信通知

为什么这么做?
假如你是一个黄牛,你可以通过这种方法抢到成千上万的票,也就是提高并发量

(2)Python中的异步与协程
假如你是黄牛,
软件自动运行之后,你要记住是这是哪个客户的票—-保存上下文
买到票后,你要去告诉相应的客户,去支付费用——恢复上下文

Python中对应的就是:
保存协程状态
生成器yield
恢复协程状态
send
事件通知
Linux系统提供的epoll

(3)例子
来源:https://github.com/denglj/aiotutorial/blob/master/part_1/generator.py

(1)注册事件和保存上下文

class Crawler:
    def __init__(self, url):
        self.url = url
        self.response = b''

    def fetch(self):
        sock = socket.socket()
        sock.setblocking(False)
        try:
            sock.connect(('example.com', 80))
        except BlockingIOError:
            pass
        f = Future()

        def on_connected():
            f.set_result(None)

        selector.register(sock.fileno(), EVENT_WRITE, on_connected)
        yield f  #注册事件和保存上下文
        selector.unregister(sock.fileno())
        get = 'GET {0} HTTP/1.0\r\nHost: example.com\r\n\r\n'.format(self.url)
        sock.send(get.encode('ascii'))

        global stopped
        while True:
            f = Future()

            def on_readable():
                f.set_result(sock.recv(4096))

            selector.register(sock.fileno(), EVENT_READ, on_readable)
            chunk = yield f #注册事件和保存上下文
            selector.unregister(sock.fileno())
            if chunk:
                self.response += chunk
            else:
                urls_todo.remove(self.url)
                if not urls_todo:
                    stopped = True
                break

(2)恢复协程状态

class Future:
    def __init__(self):
        self.result = None
        self._callbacks = []

    def add_done_callback(self, fn):
        self._callbacks.append(fn)

    def set_result(self, result):
        self.result = result
        for fn in self._callbacks:
            fn(self)

class Task:
    def __init__(self, coro):
        self.coro = coro
        f = Future()
        f.set_result(None)
        self.step(f)

    def step(self, future):
        try:
            # send会进入到coro执行, 即fetch, 直到下次yield
            # next_future 为yield返回的对象
            next_future = self.coro.send(future.result)#恢复状态
        except StopIteration:
            return
        next_future.add_done_callback(self.step)

(3)事件循环

def loop():
    while not stopped:
        # 阻塞, 直到一个事件发生
        events = selector.select()
        for event_key, event_mask in events:
            callback = event_key.data
            callback()

猜你喜欢

转载自blog.csdn.net/yz764127031/article/details/79291640
今日推荐