2016-10-09 3 views
0

Это мой код для Facebook Messenger Platform с использованием Tornado.Не удалось закончить RequestHandler в Tornado с self.finish()

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() 

Проблема заключается в том, когда я запускаю его (нехватка hub.mode арг), он будет ловить MissingArgumentError и выбросить:

File "index.py", line 20, in get 
if mode == "subscribe" and token == "secretgarden": 
UnboundLocalError: local variable 'mode' referenced before assignment 

я ожидаю, когда это поймать мой MissingArgumentError исключение, он будет возвращать 400 и завершите мой запрос. Но он все еще запускает следующий код. Я сделал что-то неправильно?

P.s: Я пробовал добавить return после self.finish(), это сработало, но я не видел, чтобы кто-то это делал. И документы, сказал:

RequestHandler.finish (порция = None) Завершает этот ответ, заканчиваясь запрос HTTP.

И я также прочитал этот вопрос: Tornado: Can I run code after calling self.finish() in an asynchronous RequestHandler?

Что-то случилось с моим кодом.

ответ

0

Вызов finish не возвращается с вашего метода. Вы должны добавить инструкцию return, иначе будет выполнен следующий оператор в вашем методе.

На самом деле, вам не нужно вызывать finish вообще: запрос Tornado обработчики автоматически вызывать finish раз в сопрограммы как get завершается.

Итак, чтобы исправить вашу проблему, замените свои self.finish() звонки операторами return.

This answer is related.

+0

Спасибо, это имеет смысл. И спасибо за подсказку. :) –

0

Возвращаясь в конце методов конечных точек является хорошим решением, однако он не будет работать, если вам нужно закончить (например, путем перенаправления) от других методов, как prepare, initialize и get_current_user, так как они не обязательно последний в стеке вызовов. «Официальный» метод заключается в том, чтобы поднять исключение tornado.web.Finish, которое будет пузыриться и нарушать выполнение из любого места в коде. Я широко использовал такие вещи:

class SomeHandler(SomeMoreGenericHandler): 

    def prepare(self): 
     super().prepare() 
     if not self.current_user: 
      self.redirect('/login') 
      raise tornado.web.Finish 
+0

И да, я знаю, что это по сути эквивалентно использованию декоратора '@ tornado.web.authenticated', но это всего лишь пример. –

Смежные вопросы