无法使用self.finish()在Tornado中完成RequestHandler

时间:2016-10-09 01:23:24

标签: tornado

这是我使用Tornado的Facebook Messenger平台的代码。

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 arg),它会捕获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(chunk = None)完成此响应,结束   HTTP请求。

我也读到了这个问题:Tornado: Can I run code after calling self.finish() in an asynchronous RequestHandler?

我的代码有问题。

2 个答案:

答案 0 :(得分:2)

调用finish不会从您的方法返回。您必须添加return语句,否则将执行方法中的下一个语句。

实际上,您根本不需要致电finish:Tornado请求处理程序会在finish之类的协程完成后自动调用get

因此,要解决您的问题,请使用self.finish()语句替换return次来电。

This answer is related.

答案 1 :(得分:0)

在端点方法结束时返回是一个很好的解决方案,但是如果您需要完成(例如通过重定向)其他方法,例如prepareinitialize和{,它将无法工作{1}},因为它们不一定是调用堆栈中的最后一个。 "官方"方法是引发tornado.web.Finish异常,它会冒出来并从代码中的任何地方中断执行。我一直在广泛使用这样的东西:

get_current_user