Python异步编程

参考:

假设存在业务逻辑 A --> B --> C

A,B,C内部都是同步的,并且把阻塞等待IO的操作用注册回调的方式取代了。

A,B,C可以是别人写好的异步库,也可以是自己写的异步的逻辑。

异步A,B负责:

  • 调用注册回调函数,以便让程序进入下一个状态。
    1. 回调函数负责提取IO返回的结果,并存储在Future对象里
    2. 回调函数也负责执行返回上文操作。
  • A,B都会返回Future对象,对象内部的内容记录了回调函数和A,B操作执行后IO返回的结果。

Future的设计目标是作为协程(coroutine)和IOLoop的媒介,从而将协程和IOLoop关联起来。

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)

协程写法可以如下:

def app():
    yield A()
    yield B()
    yield C()

事件驱动的主Loop负责检查Event,然后执行注册Event的回调函数如下:

def loop():
    events = selector.select()
    for event_key, event_mask in events:
        callback = event_key.data
        callback()

使用Task对象的Step函数

  1. 调用上文,并把下文的入口放在上文里
  2. 把IO输出的结果输出给下文

实现的方式是在上文返回的Future对象中,加入下文入口的回调函数采用。类似于Tornado的Runner:

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

    def step(self, future):
        # 1. 执行上文,得到返回的Future对象
        try:
            next_future = self.coro.send(future.result) 
        except StopIteration:
            return

        # 2. 把下文入口加入到上文的Future的回调中
        next_future.add_done_callback(self.step)

为什么要大费周章发明异步框架?

  • 性能好
  • 代码逻辑易于理解(类同步写法)

results matching ""

    No results matching ""