Search code examples
pythonerror-handlingtornado

How to Handle Python ERROR:tornado.application:Uncaught exception


I have the following code which keeps triggering a ERROR:tornado.application:Uncaught exception GET and I can't seem to figure out how to handle it appropriately?

class MainHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self, id):
        http = tornado.httpclient.AsyncHTTPClient()
        endpoint = "https://www.foobar.com/api/v1"
        foo = yield http.fetch("{}/foo/{}".format(endpoint, id), self._handle_fetch)
        bar = yield http.fetch("{}/bar/{}".format("http://www.doh.com", id), self._handle_fetch)
        // do other things at this point like serve content to user

def _handle_fetch(self, response):
    if response.error:
        print("there was an error so returning None")
        return {}
    else:
        print("everything OK so returning response")
        return response

The foo yield will succeed where as the bar yield will fail

How do I handle the exception so that I can continue to serve content to the user when the bar yield fails? (as I don't care about it succeeding)

UPDATE

I've managed to handle the error:

    try:
        foo = yield http.fetch("{}/foo/{}".format(endpoint, id), self._handle_fetch)
        bar = yield http.fetch("{}/bar/{}".format("http://www.doh.com", id), self._handle_fetch)
        print(foo.body)
        print(bar.body)
    except tornado.httpclient.HTTPError as e:
        print("Error: " + str(e))
    except Exception as e:
        print("Error: " + str(e))

But I'm trying to figure out how to identify which fetch caused the fail as I want to try and serve content still if the foo succeeds and bar fails. But iffoo` fails I want to fail the whole response and send a custom error


Solution

  • OK I managed to fix this:

    import tornado.ioloop
    import tornado.web
    import tornado.httpclient
    import html2text
    import json
    
    class MainHandler(tornado.web.RequestHandler):
        @tornado.gen.coroutine
        def get(self, id):
            http = tornado.httpclient.AsyncHTTPClient()
            endpoint = "https://www.foo.com/api/v1"
    
            try:
                foo = yield http.fetch("{}/foo/{}".format(endpoint, id))
                bar = yield http.fetch("{}/bar/{}".format("http://www.doh.com", id))
            except tornado.httpclient.HTTPError as e:
                if "bar" in e.response.effective_url:
                    bar = "change bar value"
                else:
                    foo = "change foo value"
    
            self._response(foo, bar)
    
        def _response(self, foodict, bardict):
            self.write("...")
            self.finish()
    
    if __name__ == "__main__":
        application = tornado.web.Application([
            (r"/api/v1/foobar/(\d{7})/?", MainHandler),
        ])
        application.listen(8888)
        tornado.httpclient.AsyncHTTPClient.configure("tornado.simple_httpclient.SimpleAsyncHTTPClient", max_clients=2, defaults=dict(connect_timeout=float(10), request_timeout=float(100)))
        tornado.ioloop.IOLoop.current().start()