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 need write

    something (in the example above, this is done by calling self.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







All Articles