tornado.gen — Generator-based coroutines

tornado.gen实现了基于生成器的协程.

Note

此模块中的"装饰器和生成器"方法是Python 3.5中引入的本机协程(使用async defawait )的前身. 不需要与旧版本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 ; 产生此对象将返回其结果.

您还可以产生其他可屈服对象的列表或字典,它们将同时启动并并行运行; 完成后将返回结果列表或命令:

@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中进行了更改:添加了对通过singledispatch生成asyncio期货和Twisted Deferreds的singledispatch .

Decorators

tornado.gen.coroutine(func: Callable[[...], Generator[Any, Any, _T]]) → Callable[[...], Future[_T]][source]

异步发电机的装饰器.

For compatibility with older versions of Python, coroutines may also “return” by raising the special exception Return(value).

使用此装饰器的函数将返回Future .

Warning

当协程内部发生异常时,异常信息将存储在Future对象中. 您必须检查Future对象的结果,否则您的代码可能不会注意到该异常. 这意味着如果从另一个协程调用该函数,则使用IOLoop.run_sync类的IOLoop.run_sync进行顶级调用,或者将Future传递给IOLoop.add_future ,从而产生该函数.

在版本6.0中更改: callback参数已删除. 请使用返回的等待对象.

exception tornado.gen.Return(value: Any = None)[source]

coroutine返回值的特殊异常.

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

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

在Python 3.3中,不再需要该异常: return语句可以直接用于返回值(以前的yield和带有值的return不能在同一函数中组合).

与return语句类似,value参数是可选的,但永远不需要raise gen.Return() . return语句可以不带参数使用.

Utility functions

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

在超时中包装Future (或其他可产生收益的对象).

如果输入future在timeout之前未完成,则引发tornado.util.TimeoutError ,它可以以IOLoop.add_timeout允许的任何形式指定(即datetime.timedelta或相对于IOLoop.time的绝对时间).

如果包装的Future在超时后失败,则将记录该异常,除非它是quiet_exceptions包含的类型(可能是异常类型或一系列类型)或asyncio.CancelledError .

超时到期时不会取消包装的Future ,从而可以重用它. asyncio.wait_for类似于此功能,但是它会在超时时取消包装的Future .

New in version 4.0.

在版本4.1中进行了更改:添加了quiet_exceptions参数和未处理异常的记录.

在版本4.4中进行了更改:增加了对Future以外的其他可屈服对象的支持.

在6.0.3版中进行了更改: asyncio.CancelledError现在始终被视为"安静".

tornado.gen.sleep(duration: float) → Future[None][source]

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

当用于yield在协程,这是一个非阻挡类似物time.sleep (其不应该在协程,因为它阻止了使用):

yield gen.sleep(0.5)

请注意,单独调用此函数不会执行任何操作. 您必须等待Future返回(通常通过屈服).

4.1版中的新功能.

class tornado.gen.WaitIterator(*args, **kwargs)[source]

提供一个迭代器,以在等待完成时产生结果.

产生一组这样的等待:

results = yield [awaitable1, awaitable2]

暂停协程,直到awaitable1awaitable2返回,然后使用两个awaitables的结果重新启动协程. 如果任何一个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来从输入列表中获取可WaitIterator.current_index的索引. (如果在WaitIterator的构造中使用了关键字参数,则current_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[source]

如果此迭代器没有更多结果,则返回True.

next() → _asyncio.Future[source]

Returns a Future that will yield the next available result.

请注意,此Future将与任何输入都不是同一对象.

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

并行运行多个异步操作.

children可以是列表或字典,其值是可产生对象. multi()返回一个新的yieldable对象,该对象解析为包含其结果的并行结构. 如果children是列表,则结果是相同顺序的结果列表; 如果是字典,则结果为具有相同键的字典.

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

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

如果有任何孩子提出异常,则multi()将提出第一个. 除非所有其他类型都包含在quiet_exceptions参数中,否则将记录所有其他内容.

在基于yield的协程中,通常不需要直接调用此函数,因为协程运行程序将在产生列表或字典时自动执行此功能. 但是,有必要在基于await的协程中,或传递quiet_exceptions参数.

由于历史原因,该函数在名称multi()Multi()下可用.

取消multi()返回的Future不会取消其子级. asyncio.gathermulti()相似,但是它确实取消了其子级.

在版本4.2中进行了更改:如果多个Yieldable失败,则将记录第一个(引发的)之后的任何异常. 添加了quiet_exceptions参数以禁止对所选异常类型进行此日志记录.

在版本4.3中进行了更改:用统一的函数multi代替了类Multi和函数multi_future . 增加了对除YieldPointFuture以外的其他可YieldPoint支持.

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

等待并行的多个异步期货.

从Tornado 6.0开始,此功能与multi完全相同.

版本4.0中的新功能.

在版本4.2中更改:如果多个Futures失败,则将记录第一个(引发的)之后的任何异常. 添加了quiet_exceptions参数以禁止对所选异常类型进行此日志记录.

自版本4.3起不推荐使用: Use multi instead.

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

将产生的对象转换为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[source]

Converts x into a Future.

如果x已经是Future ,则简单地返回它; 否则,它将包装在新的Future . 当您不知道f()是否返回Future时,此方法适合用作result = yield gen.maybe_future(f()) .

从版本4.3开始不推荐使用:此函数仅处理Futures ,而不处理其他可转换对象. 而不是maybe_future ,检查您期望的非未来结果类型(通常只是None ),并yield任何未知的结果.

tornado.gen.is_coroutine_function(func: Any) → bool[source]

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

4.5版的新功能.

tornado.gen.moment