【问题标题】:Can't call result() on futures in tornado无法在龙卷风的期货上调用 result()
【发布时间】:2015-09-19 06:09:55
【问题描述】:

我想使用 python 库 tornado(4.2 版)执行一些异步 HTTP 请求。但是,我不能强迫未来完成(使用result()),因为我得到一个异常:“DummyFuture 不支持结果阻塞”。

我有 python 3.4.3,因此未来的支持应该是标准库的一部分。 concurrent.py 的文档说:

Tornado 将使用concurrent.futures.Future(如果可用); 否则它将使用此模块中定义的兼容类。

下面提供了我正在尝试做的最小示例:

from tornado.httpclient import AsyncHTTPClient;

future = AsyncHTTPClient().fetch("http://google.com")
future.result()

如果我正确理解了我的问题,它的发生是因为 concurrent.futures.Future 的导入以某种方式未被使用。 tornado 中的相关代码似乎在 concurrent.py 中,但我在理解问题的确切位置方面并没有真正取得进展。

【问题讨论】:

  • “Tornado 将使用 concurrent.futures.Future 如果可用”的评论已过时; Tornado 4.x 总是使用自己的 Future 实现。

标签: python tornado


【解决方案1】:

尝试创建另一个Future 并使用add_done_callback

From Tornado documentation

from tornado.concurrent import Future

def async_fetch_future(url):
    http_client = AsyncHTTPClient()
    my_future = Future()
    fetch_future = http_client.fetch(url)
    fetch_future.add_done_callback(
        lambda f: my_future.set_result(f.result()))
    return my_future

但是你仍然需要用 ioloop 解决未来,像这样:

# -*- coding: utf-8 -*-
from tornado.concurrent import Future
from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop


def async_fetch_future():
    http_client = AsyncHTTPClient()
    my_future = Future()
    fetch_future = http_client.fetch('http://www.google.com')
    fetch_future.add_done_callback(
        lambda f: my_future.set_result(f.result()))
    return my_future

response = IOLoop.current().run_sync(async_fetch_future)

print(response.body)

另一种方法是使用tornado.gen.coroutinedecorator,如下所示:

# -*- coding: utf-8 -*-
from tornado.gen import coroutine
from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop


@coroutine
def async_fetch_future():
    http_client = AsyncHTTPClient()
    fetch_result = yield http_client.fetch('http://www.google.com')
    return fetch_result

result = IOLoop.current().run_sync(async_fetch_future)

print(result.body)

coroutine 装饰器使函数返回Future

【讨论】:

  • 这对我有用,谢谢!我想我明白了。我不能使用“原始”期货,因为它们不是 IOLoop 的一部分,我需要一些方法将它们添加到其中。对吗?
  • 你为什么不能'''def async_fetch_future(): http_client = AsyncHTTPClient() my_future = Future() fetch_future = http_client.fetch('google.com')''' 然后把这个函数进入 IOLOOP?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
  • 2016-07-07
相关资源
最近更新 更多