Asynchronous 如何在Tornado中将异步函数和gen函数包装在一起?
如何在Tornado中将异步函数和gen函数包装在一起? 我的代码如下所示,错误是“Future”对象没有属性“body” 我把装饰师放错地方了吗Asynchronous 如何在Tornado中将异步函数和gen函数包装在一起?,asynchronous,generator,tornado,Asynchronous,Generator,Tornado,如何在Tornado中将异步函数和gen函数包装在一起? 我的代码如下所示,错误是“Future”对象没有属性“body” 我把装饰师放错地方了吗 import tornado.httpclient import tornado.web import tornado.gen import tornado.httpserver import tornado.ioloop class Class1(tornado.web.RequestHandler): @tornado.web.asy
import tornado.httpclient
import tornado.web
import tornado.gen
import tornado.httpserver
import tornado.ioloop
class Class1(tornado.web.RequestHandler):
@tornado.web.asynchronous
def post(self, *args, **kwargs):
url = self.get_argument('url', None)
response = self.json_fetch('POST', url, self.request.body)
self.write(response.body)
self.finish()
@tornado.gen.engine
def json_fetch(self, method, url, body=None, *args, **kwargs):
client = tornado.httpclient.AsyncHTTPClient()
headers = tornado.httputil.HTTPHeaders({"content-type": "application/json charset=utf-8"})
request = tornado.httpclient.HTTPRequest(url, method, headers, body)
yield tornado.gen.Task(client.fetch, request)
在这个代码示例中,您不需要“异步”。“gen.engine”已过时,请使用“coroutine”。现在,您通常也不需要经常使用“gen.Task”。对代码进行四项更改:
class ClubCreateActivity(tornado.web.RequestHandler):
@tornado.gen.coroutine
def post(self, *args, **kwargs):
url = self.get_argument('url', None)
response = yield self.json_fetch('POST', url, self.request.body)
self.write(response.body)
@tornado.gen.coroutine
def json_fetch(self, method, url, body=None, *args, **kwargs):
client = tornado.httpclient.AsyncHTTPClient()
headers = tornado.httputil.HTTPHeaders({"content-type": "application/json charset=utf-8"})
request = tornado.httpclient.HTTPRequest(url, method, headers, body)
response = yield client.fetch(request)
raise gen.Return(response)
进一步阅读:
from tornado.concurrent import Future
def json_fetch(self, method, url, body=None, *args, **kwargs):
http_client = tornado.httpclient.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
或者像这样(来自A.Jesse Jiryu Davis的回答):
*将“post”封装在“gen.coroutine”中,并对json_fetch进行“yield”调用
**“raise gen.Return(response)”仅适用于Python2,在Python3.3及更高版本中,您应该编写“Return response”
感谢A.Jesse Jiryu Davis提供的链接“Tornado异步请求处理程序”,在那里找到了“异步和非阻塞I/O”。我去学习gen.coroutine的知识。似乎我必须这样写,因为我使用的是Python 2?raise gen.Return(response.body)我如上所述尝试过:AttributeError:'NoneType'对象没有属性'body',为什么我仍然需要在函数post中使用yiled?json_fetch已经返回了一个future对象?是的,json_fetch返回一个future。为了等待将来对响应进行解析,“post”函数必须让步。yield暂停“post”直到“json_fetch”完成,然后“post”以响应值继续。
from tornado import gen
@gen.coroutine
def json_fetch(self, method, url, body=None, *args, **kwargs):
http_client = tornado.httpclient.AsyncHTTPClient()
headers = tornado.httputil.HTTPHeaders({"content-type": "application/json charset=utf-8"})
request = tornado.httpclient.HTTPRequest(url, method, headers, body)
response = yield http_client.fetch(request)
raise gen.Return(response)