Signals

Flask allows you to act on events and customise behaviour using signals.

Signals require Blinker to be installed, though many app hooks don’t use signals, just a list of callables.

Signals vs Hooks

Flask signals use Blinker and are usually informational (e.g. you want to watch for errors and log them).

Flask hooks (usually spotted by being methods on blueprints or apps) don’t require Blinker and allow you to modify the request or response. These change the behaviour of the app (or blueprint).

Typically you want hooks for changing behaviour (e.g. authentication or error handling) and signals for recording events (e.g. logging).

Caveat

I got bitten by the difference between flask.request_finished and flask.got_request_exception, the former doesn’t fire when there is an error (HTTP 500) as Flask doesn’t hit that part of the code, while got_request_exception fires on all exceptions. I wound up putting two handlers in place.

Flask 0.9 Lifecycle

Flask 0.9 full_dispatch_request():

request_started.send(app) -> signal
rv = preprocess_request()
  rv = [fn() for fn in before_request_funcs (@before_request)]
(rv = dispatch_request() calls actual view)
except: rv = handle_user_exception(e)
  rv = [fn(e) for fn in error_handler_spec[e | status_code] (@errorhandler)]
(response = make_response(rv) uses response_class)
response = process_response(response)
  response = [fn(response) for fn in after_request_funcs (@after_request)]
request_finished.send(app, response=response) -> signal

Flask 0.9 hooks to modify content:

@before_request (can give its own response, e.g. auth denied)
@errorhandler(e) (can work off exception type or status code, can set its own response)
@after_request(response) (can override the response)

Flask 0.9 signals:

request_started.send(app)
got_request_exception.send(app, exception=e)
request_finished.send(app, response=response)
request_tearing_down.send(app, exc=exc) (@teardown_request(exception) (always called at the end, possibly passed an exception)

Code

Signals let you change the behaviour of your app or blueprint

pythonie.blueprints.signals.authenticate()[source]

Performs authentication based on HTTP params

Looks for a password param.

pythonie.blueprints.signals.handle_errors(e)[source]

Ensure exceptions always return JSON errors

Note how this is registered with either an exception type or a HTTP code.

pythonie.blueprints.signals.index()[source]

A simple demo of authentication

To see in action go to http://building-webapps-with-flask.herokuapp.com/signals/?password=sekret

pythonie.blueprints.signals.notjson()[source]

A simple demo of very specific error handling

To see in action go to http://building-webapps-with-flask.herokuapp.com/signals/not.json?password=sekret

URLs

GET /signals/not.json

A simple demo of very specific error handling

To see in action go to http://building-webapps-with-flask.herokuapp.com/signals/not.json?password=sekret

GET /signals/

A simple demo of authentication

To see in action go to http://building-webapps-with-flask.herokuapp.com/signals/?password=sekret

GET /

To see this in action go to http://building-webapps-with-flask.herokuapp.com/