Почему вызывается только одна функция Flask teardown_request, когда представление вызывает исключение?

Это простое приложение имеет два обработчика teardown_request, и я ожидаю, что они оба будут вызываться для каждого запроса, независимо от того, что происходит в реализации представления, в соответствии с документация

import flask
import werkzeug.exceptions

app = flask.Flask(__name__)

@app.teardown_request
def teardown1(response):
    print "Teardown 1"
    return response

@app.teardown_request
def teardown2(response):
    print "Teardown 2"
    return response

@app.route("/")
def index():
    return "chunky bacon"

@app.route("/httpexception")
def httpexception():
    raise werkzeug.exceptions.BadRequest("no bacon?")

@app.route("/exception")
def exception():
    raise Exception("bacoff")

if __name__ == "__main__":
    app.run(port=5000)

Однако, когда я запускаю его и делаю запросы к трем представлениям по очереди, я получаю следующий вывод:

Teardown 2
Teardown 1
127.0.0.1 - - [15/Nov/2011 18:53:16] "GET / HTTP/1.1" 200 -

Teardown 2
Teardown 1
127.0.0.1 - - [15/Nov/2011 18:53:27] "GET /httpexception HTTP/1.1" 400 -

Teardown 2
127.0.0.1 - - [15/Nov/2011 18:53:33] "GET /exception HTTP/1.1" 500 -

Только одна из функций teardown_request вызывается, когда последним представлением вызывается исключение, не являющееся производным от werkzeug.exceptions.HTTPException. Любые идеи, почему, или это ошибка в колбе?


person Day    schedule 15.11.2011    source источник


Ответы (1)


Только что сам нашел ответ.

Функции teardown_request не должны принимать ответ и возвращать ответ, как after_request делает. По-видимому, они принимают аргумент, который обычно равен None, если только представление не вызывает Exception, который не является производным от HttpException, и в этом случае им передается это.

По-видимому, они также не должны возвращать указанное исключение, иначе вы получите нарушенное поведение, которое я продемонстрировал.

Чтобы исправить это, teardown_request функции приложения должны выглядеть так:

@app.teardown_request
def teardown1(exc):
    print "Teardown 1 {0!r}".format(exc)

@app.teardown_request
def teardown2(exc):
    print "Teardown 2 {0!r}".format(exc)

Что затем дает ожидаемый результат для всех трех представлений:

Teardown 2 None
Teardown 1 None
127.0.0.1 - - [15/Nov/2011 19:20:03] "GET / HTTP/1.1" 200 -

Teardown 2 None
Teardown 1 None
127.0.0.1 - - [15/Nov/2011 19:20:10] "GET /httpexception HTTP/1.1" 400 -

Teardown 2 Exception('bacoff',)
Teardown 1 Exception('bacoff',)
127.0.0.1 - - [15/Nov/2011 19:20:18] "GET /exception HTTP/1.1" 500 -

(с добавлением некоторой дополнительной отладки для печати того, что передается обработчикам teardown_request)

person Day    schedule 15.11.2011