tornado.gen ——基于生成器的协同程序

tornado.gen 实现基于生成器的协同程序。

注解

本模块中的“decorator and generator”方法是本机协程(使用 async defawait )在python 3.5中引入。不需要与旧版本的Python兼容的应用程序应该使用本机协程。这个模块的某些部分对于本机协程仍然有用,特别是 multisleepWaitIteratorwith_timeout . 其中一些功能在 asyncio 也可以使用模块,尽管这两个模块未必100%兼容。

协同程序提供了一种在异步环境中工作比链接回调更简单的方法。使用协程的代码在技术上是异步的,但它是作为单个生成器而不是单独的函数集合编写的。

例如,这里有一个基于协程的处理程序:

class GenAsyncHandler(RequestHandler):
    @gen.coroutine
    def get(self):
        http_client = AsyncHTTPClient()
        response = yield http_client.fetch("http://example.com")
        do_something_with_response(response)
        self.render("template.html")

Tornado中的异步函数返回 AwaitableFuture ;生成此对象将返回其结果。

您还可以生成其他可扩展对象的列表或dict,这些对象将同时启动并并行运行;结果列表或dict将在完成后返回:

@gen.coroutine
def get(self):
    http_client = AsyncHTTPClient()
    response1, response2 = yield [http_client.fetch(url1),
                                  http_client.fetch(url2)]
    response_dict = yield dict(response3=http_client.fetch(url3),
                               response4=http_client.fetch(url4))
    response3 = response_dict['response3']
    response4 = response_dict['response4']

如果 tornado.platform.twisted 是进口的,也有可能产生 Twisted 的 Deferred 物体。见 convert_yielded 用于扩展此机制的函数。

在 3.2 版更改: 添加了 Dict 支持。

在 4.1 版更改: 增加屈服支撑 asyncio 期货和 通过 singledispatch 的 Twisted Deferreds .

装饰器

tornado.gen.coroutine(func: Callable[[...], Generator[Any, Any, _T]]) Callable[[...], Future[_T]][源代码]
tornado.gen.coroutine(func: Callable[[...], tornado.gen._T]) Callable[[...], Future[_T]]

异步生成器的装饰器。

为了与旧版本的python兼容,协程还可以通过引发特殊的异常来“返回” Return(value) .

带有此修饰符的函数返回 Future .

警告

当异常发生在协同程序内时,异常信息将存储在 Future 对象。您必须检查 Future 对象,或者异常可能会被代码忽略。这意味着如果从另一个协程调用函数,则使用类似 IOLoop.run_sync 对于顶级呼叫,或通过 FutureIOLoop.add_future .

在 6.0 版更改: 这个 callback 参数已删除。请改用返回的等待对象。

exception tornado.gen.Return(value: Optional[Any] = None)[源代码]

从返回值的特殊异常 coroutine .

如果引发此异常,则将其值参数用作协程的结果:

@gen.coroutine
def fetch_json(url):
    response = yield AsyncHTTPClient().fetch(url)
    raise gen.Return(json_decode(response.body))

在python 3.3中,不再需要这个异常: return 语句可直接用于返回值(以前 yieldreturn 不能在同一函数中组合WITH值)。

与RETURN语句类似,value参数是可选的,但从来没有必要 raise gen.Return() . 这个 return 语句不能与参数一起使用。

效用函数

tornado.gen.with_timeout(timeout: Union[float, datetime.timedelta], future: Yieldable, quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())[源代码]

包裹甲 Future (或其他可传递对象)超时。

加薪 tornado.util.TimeoutError 如果输入的未来在之前没有完成 timeout ,可按允许的任何形式指定。 IOLoop.add_timeout (即 datetime.timedelta 或相对于 IOLoop.time

如果包裹 Future 在超时后失败,除非异常是包含在 quiet_exceptions (可以是异常类型或类型序列),或者 asyncio.CancelledError .

包裹 Future 不会在超时到期时取消,从而允许重复使用。 asyncio.wait_for 与此函数类似,但它确实取消了包装 Future 超时。

4.0 新版功能.

在 4.1 版更改: 增加了 quiet_exceptions 参数和未处理异常的日志记录。

在 4.4 版更改: 添加了对除 Future .

在 6.0.3 版更改: asyncio.CancelledError 现在总是被认为是“安静”。

在 6.2 版更改: tornado.util.TimeoutError 现在是的别名 asyncio.TimeoutError

tornado.gen.sleep(duration: float) Future[None][源代码]

返回A Future 在给定的秒数后解析。

当使用时 yield 在协程中,这是一个非阻塞的类似物 time.sleep (不应在协程中使用,因为它是阻塞的)::

yield gen.sleep(0.5)

请注意,单独调用此函数并不起任何作用;必须等待 Future 它返回(通常通过屈服)。

4.1 新版功能.

class tornado.gen.WaitIterator(*args: _asyncio.Future, **kwargs: _asyncio.Future)[源代码]

提供一个迭代器以在等待的结果完成时生成这些结果。

产生一组这样的等待:

results = yield [awaitable1, awaitable2]

暂停连体衣直到两者都停止 awaitable1awaitable2 返回,然后用两个等待的结果重新启动协同程序。如果任何一个waitable引发异常,表达式将引发该异常,所有结果都将丢失。

如果您需要尽快获得每个等待的结果,或者如果您需要一些等待的结果,即使其他人产生错误,也可以使用 WaitIterator ::

wait_iterator = gen.WaitIterator(awaitable1, awaitable2)
while not wait_iterator.done():
    try:
        result = yield wait_iterator.next()
    except Exception as e:
        print("Error {} from {}".format(e, wait_iterator.current_future))
    else:
        print("Result {} received from {} at {}".format(
            result, wait_iterator.current_future,
            wait_iterator.current_index))

因为结果一旦可用就返回迭代器的输出 与输入参数的顺序不同 . 如果需要知道哪个未来产生了当前结果,可以使用这些属性 WaitIterator.current_futureWaitIterator.current_index 从输入列表中获取可等待的索引。(如果关键字参数用于 WaitIteratorcurrent_index 将使用相应的关键字)。

在Python 3.5上, WaitIterator 实现异步迭代器协议,因此它可以与 async for 语句(请注意,在此版本中,如果有任何值引发异常,则整个迭代将中止,而上一个示例可能会继续出现个别错误)::

async for result in gen.WaitIterator(future1, future2):
    print("Result {} received from {} at {}".format(
        result, wait_iterator.current_future,
        wait_iterator.current_index))

4.1 新版功能.

在 4.3 版更改: 补充 async for 支持python 3.5。

done() bool[源代码]

如果此迭代器没有更多结果,则返回true。

next() _asyncio.Future[源代码]

返回A Future 这将产生下一个可用的结果。

注意这个 Future 将不是任何输入的同一对象。

tornado.gen.multi(Union[List[Yieldable], Dict[Any, Yieldable]], quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())[源代码]

并行运行多个异步操作。

children 可以是列表,也可以是值为可扩展对象的dict。 multi() 返回一个新的可扩展对象,该对象解析为包含其结果的并行结构。如果 children 是一个列表,结果是按相同顺序排列的结果列表;如果是一个dict,则结果是具有相同键的dict。

也就是说, results = yield multi(list_of_futures) 等于:

results = []
for future in list_of_futures:
    results.append(yield future)

如果有孩子提出异议, multi() 将升起第一个。所有其他类型都将被记录,除非它们属于 quiet_exceptions 参数。

在一个 yield -基于协程,通常不需要直接调用这个函数,因为当生成一个列表或dict时,协程运行程序会自动调用这个函数。但是,有必要 await -基于协程,或通过 quiet_exceptions 参数。

此函数在以下名称下可用 multi()Multi() 因为历史原因。

取消A Future 返回的 multi() 不取消其子项。 asyncio.gather 类似于 multi() 但它确实取消了它的子项。

在 4.2 版更改: 如果多个yieldables失败,则会记录第一个(引发的)之后的任何异常。增加了 quiet_exceptions 参数来禁止所选异常类型的日志记录。

在 4.3 版更改: 替换了班级 Multi 以及功能 multi_future 具有统一的功能 multi . 增加了对Yieldables的支持,而不是 YieldPointFuture .

tornado.gen.multi_future(Union[List[Yieldable], Dict[Any, Yieldable]], quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())[源代码]

同时等待多个异步期货。

由于Tornado 6.0,此函数与 multi .

4.0 新版功能.

在 4.2 版更改: 中频倍数 Futures 失败,将记录第一个(引发的)之后的任何异常。增加了 quiet_exceptions 参数来禁止所选异常类型的日志记录。

4.3 版后已移除: 使用 multi 相反。

tornado.gen.convert_yielded(yielded: Union[None, Awaitable, List[Awaitable], Dict[Any, Awaitable], concurrent.futures._base.Future]) _asyncio.Future[源代码]

将生成的对象转换为 Future .

默认实现接受列表、字典和预购。这有一个副作用,即启动任何没有自己启动的协同程序,类似于 asyncio.ensure_future .

如果 singledispatch 库可用,可以扩展此功能以支持其他类型。例如::

@convert_yielded.register(asyncio.Future)
def _(asyncio_future):
    return tornado.platform.asyncio.to_tornado_future(asyncio_future)

4.1 新版功能.

tornado.gen.maybe_future(x: Any) _asyncio.Future[源代码]

皈依者 x 变成一个 Future .

如果 x 已经是 Future ,它只是简单地返回;否则它将被包装在新的 Future . 这适合用作 result = yield gen.maybe_future(f()) 当你不知道 f() 返回A Future 或者没有。

4.3 版后已移除: 此函数只处理 Futures ,而不是其他可移动的对象。而不是 maybe_future ,检查您期望的非未来结果类型(通常只是 Noneyield 有什么不知道的。

tornado.gen.is_coroutine_function(func: Any) bool[源代码]

返回是否 func 是协程函数,即用 coroutine .

4.5 新版功能.

tornado.gen.moment

允许IOLoop运行一次迭代的特殊对象。

这在正常使用中是不需要的,但它可以帮助长期运行的协同程序,这些协同程序可能会产生即时准备好的期货。

用途: yield gen.moment

在本地协程中,相当于 yield gen.momentawait asyncio.sleep(0) .

4.0 新版功能.

4.5 版后已移除: yield None (或) yield 现在等价于 yield gen.moment .