Tornado uses AsyncHTTPClient and gen to request url, use raise gen.Return gets exceptions
I am new to tornado so I follow the tornado guide to practice when I come to using Corouts the example says from tornado import gen
@gen.coroutine
def fetch_coroutine(url):
http_client = AsyncHTTPClient()
response = yield http_client.fetch(url)
# In Python versions prior to 3.3, returning a value from
# a generator is not allowed and you must use
# raise gen.Return(response.body)
# instead.
return response.body
when I run this test it raises a SyntaxError 'return' with an argument inside the generator , so I will uncomment the advice like: import tornado.httpserver import tornado.ioloop import tornado. import tornado.web
from tornado.options import define, options
define("port", default=8888, help="run on the given port", type=int)
from tornado import gen
from tornado.httpclient import AsyncHTTPClient
@gen.coroutine
def fetch_coroutine(url):
http_client = AsyncHTTPClient()
response = yield http_client.fetch(url)
#return response.body
raise gen.Return(response.body)
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
data = fetch_coroutine(url = "http://www.baidu.com")
self.write(data)
print data
def main():
tornado.options.parse_command_line()
application = tornado.web.Application([
(r"/", MainHandler),
])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
but it throws an exception:
[E 140925 17:35:53 web:1407] Uncaught exception GET / (::1)
HTTPServerRequest(protocol='http', host='localhost:8888', method='GET', uri='/', version='HTTP/1.1', remote_ip='::1', headers={'Accept-Language': 'zh-TW,zh;q=0.8,zh-CN;q=0.6,en;q=0.4', 'Accept-Encoding': 'gzip,deflate,sdch', 'Host': 'localhost:8888', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36', 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0', 'If-None-Match': '"e02aa1b106d5c7c6a98def2b13005d5b84fd8dc8"'})
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/tornado-4.0.2-py2.7-macosx-10.9-intel.egg/tornado/web.py", line 1332, in _execute
result = method(*self.path_args, **self.path_kwargs)
File "helloworld.py", line 39, in get
self.write(data)
File "/Library/Python/2.7/site-packages/tornado-4.0.2-py2.7-macosx-10.9-intel.egg/tornado/web.py", line 656, in write
raise TypeError("write() only accepts bytes, unicode, and dict objects")
TypeError: write() only accepts bytes, unicode, and dict objects
[E 140925 17:35:53 web:1811] 500 GET / (::1) 3.94ms
+3
source to share
1 answer
The documentation has a very similar example :
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")
In short:
- In python 2.x you cannot return something inside a block, decorated
@gen.coroutine
, only single is allowedreturn
- In python 2.x, if you need to return something inside the @ gen.coroutine block, use
raise gen.Return
as you understand correctly - You don't need to return anything in the method
get
to respond to some data to the client. You needwrite
something (in the example above, this is done by callingself.render
).
So, replace this code
do_something_with_response(response)
self.render("template.html")
with this:
self.write(response.body)
self.finish()
self.finish()
will complete the response by completing the HTTP request. It is automatically called by the method self.render
.
Final request handler :
from tornado import gen
from tornado.web import RequestHandler
from tornado.httpclient import AsyncHTTPClient
class GenAsyncHandler(RequestHandler):
@gen.coroutine
def get(self):
http_client = AsyncHTTPClient()
response = yield http_client.fetch("http://google.com")
self.write(response.body)
self.finish()
+7
source to share