[英]Python Tornado Async Fetching of URLs
In the following code example I have a function do_async_thing
which appears to return a Future
, even though I'm not sure why? 在以下代码示例中,我有一个函数
do_async_thing
,该函数似乎返回Future
,即使我不确定为什么?
import tornado.ioloop
import tornado.web
import tornado.httpclient
@tornado.gen.coroutine
def do_async_thing():
http = tornado.httpclient.AsyncHTTPClient()
response = yield http.fetch("http://www.google.com/")
return response.body
class MainHandler(tornado.web.RequestHandler):
def get(self):
x = do_async_thing()
print(x) # <tornado.concurrent.Future object at 0x10753a6a0>
self.set_header("Content-Type", "application/json")
self.write('{"foo":"bar"}')
self.finish()
if __name__ == "__main__":
app = tornado.web.Application([
(r"/foo/?", MainHandler),
])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
You'll see that I yield
the call to fetch
and in doing so I should have forced the value to be realised (and subsequently been able to access the body
field of the response). 您会看到我
yield
了对fetch
的调用,并且这样做我应该强制实现该值(随后便能够访问响应的body
字段)。
What's more interesting is how I can even access the body
field on a Future and not have it error (as far as I know a Future has no such field/property/method) 更有意思的是,我什至可以访问Future上的
body
字段,而不会出现错误(据我所知Future没有此类字段/属性/方法)
So does anyone know how I can: 有谁知道我该怎么做:
do_async_thing
makes multiple async url fetches do_async_thing
进行多个异步URL提取 Now it's worth noting that because I was still getting a Future back I thought I would try adding a yield
to prefix the call to do_async_thing()
(eg x = yield do_async_thing()
) but that gave me back the following error: 现在值得注意的是,因为我仍在获得Future,所以我想我会尝试添加一个
yield
来do_async_thing()
的调用作为前缀(例如x = yield do_async_thing()
),但是这给了我以下错误:
tornado.gen.BadYieldError: yielded unknown object <generator object get at 0x1023bc308>
I also looked at doing something like this for the second point: 我还考虑了第二点:
def do_another_async_thing():
http = tornado.httpclient.AsyncHTTPClient()
a = http.fetch("http://www.google.com/")
b = http.fetch("http://www.github.com/")
return a, b
class MainHandler(tornado.web.RequestHandler):
def get(self):
y = do_another_async_thing()
print(y)
But again this returns: 但这又返回了:
<tornado.concurrent.Future object at 0x102b966d8>
Where as I would've expected a tuple of Futures at least? 正如我所期望的那样,至少在哪里有期货的元组? At this point I'm unable to resolve these Futures without getting an error such as:
在这一点上,我无法解决这些期货,而不会出现以下错误:
tornado.gen.BadYieldError: yielded unknown object <generator object get at 0x1091ac360>
Below is an example that works (as per answered by A. Jesse Jiryu Davis) 下面是一个有效的示例(根据A. Jesse Jiryu Davis的回答)
But I've also added another example where by I have a new function do_another_async_thing
which makes two async HTTP requests (but evaluating their values are a little bit more involved as you'll see): 但是,我还添加了另一个示例,其中有一个新函数
do_another_async_thing
,该函数发出两个异步HTTP请求(但是,如您所见,评估它们的值会涉及更多点):
def do_another_async_thing():
http = tornado.httpclient.AsyncHTTPClient()
a = http.fetch("http://www.google.com/")
b = http.fetch("http://www.github.com/")
return a, b
@tornado.gen.coroutine
def do_async_thing():
http = tornado.httpclient.AsyncHTTPClient()
response = yield http.fetch("http://www.google.com/")
return response.body
class MainHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
x = yield do_async_thing()
print(x) # displays HTML response
fa, fb = do_another_async_thing()
fa = yield fa
fb = yield fb
print(fa.body, fb.body) # displays HTML response for each
It's worth clarifying: you might expect the two yield
statements for do_another_async_thing
to cause a blockage. 值得澄清:您可能希望
do_another_async_thing
的两个yield
语句导致阻塞。 But here is a breakdown of the steps that are happening: 但是,这是正在发生的步骤的分解:
do_another_async_thing
returns immediately a tuple with two Futures do_another_async_thing
立即返回带有两个Future的元组 yield
the first tuple which causes the program to be blocked until the value is realised yield
第一个元组,它导致程序被阻塞,直到实现该值为止 yield
again, causing the program to block until the value is realised yield
,导致程序阻塞,直到实现该值 yield
returns practically instantly yield
收益几乎立即返回 Coroutines return futures. 协程返回期货。 To wait for the coroutine to complete, the caller must also be a coroutine, and must yield the future.
为了等待协程完成,调用方还必须是协程,并且必须产生未来。 So:
所以:
@gen.coroutine
def get(self):
x = yield do_async_thing()
For more info see Refactoring Tornado Coroutines . 有关更多信息,请参见重构龙卷风协程 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.