Can not finish a RequestHandler in Tornado with self.finish()
This is my code for Facebook Messenger Platform using Tornado.
class IndexHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
try:
mode = self.get_argument("hub.mode")
token = self.get_argument("hub.verify_token")
challenge = self.get_argument("hub.challenge")
except tornado.web.MissingArgumentError:
self.set_status(400)
self.write("Bad request")
self.finish()
if mode == "subscribe" and token == "secretgarden":
self.set_status(200)
self.write(challenge)
self.finish()
else:
self.set_status(403)
self.write("GTFO")
self.finish()
The problem is when I run it (lack of hub.mode
arg), it will catch MissingArgumentError
and throw out:
File "index.py", line 20, in get
if mode == "subscribe" and token == "secretgarden":
UnboundLocalError: local variable 'mode' referenced before assignment
I expect when it catch my MissingArgumentError
exception, it will return 400
and end my request. But it still running next code. Did I do anything wrong?
Ps: I have tried add return
after self.finish()
, it worked, but I have not seen anyone do it. And the docs said:
RequestHandler.finish(chunk=None) Finishes this response, ending the HTTP request.
And I also read this question: Tornado: Can I run code after calling self.finish() in an asynchronous RequestHandler?
Something wrong with my code.
Calling finish
does not return from your method. You have to add a return
statement, otherwise the next statement in your method is executed.
Actually, you don't need to call finish
at all: Tornado request handlers automatically call finish
once a coroutine like get
completes.
So, to fix your problem, replace your self.finish()
calls with return
statements.
This answer is related.
Returning at the end of endpoint methods is a good solution, however it won't work if you need to finish (eg by redirecting) from other methods like prepare
, initialize
and get_current_user
, as they are not necessarily last in the call stack. The "official" method is to raise the tornado.web.Finish
exception, which will bubble up and break execution from anywhere in the code. I've been using things like this extensively:
class SomeHandler(SomeMoreGenericHandler):
def prepare(self):
super().prepare()
if not self.current_user:
self.redirect('/login')
raise tornado.web.Finish
链接地址: http://www.djcxy.com/p/27856.html
上一篇: 如何做单元测试龙卷风+异步def?