New in version 0.6.
Starting with Flask 0.6, there is integrated support for signalling in Flask. This support is provided by the excellent blinker library and will gracefully fall back if it is not available.
在Flask 0.6版本加入了对信号的支持。该项功能由`blinker`库提供支持，如果没有安装该库 程序将不做任何处理。
What are signals? Signals help you decouple applications by sending notifications when actions occur elsewhere in the core framework or another Flask extensions. In short, signals allow certain senders to notify subscribers that something happened.
Flask comes with a couple of signals and other extensions might provide
more. Also keep in mind that signals are intended to notify subscribers
and should not encourage subscribers to modify data. You will notice that
there are signals that appear to do the same thing like some of the
builtin decorators do (eg:
request_started is very similar
before_request()). There are however difference in
how they work. The core
before_request() handler for
example is executed in a specific order and is able to abort the request
early by returning a response. In contrast all signal handlers are
executed in undefined order and do not modify any data.
The big advantage of signals over handlers is that you can safely subscribe to them for the split of a second. These temporary subscriptions are helpful for unittesting for example. Say you want to know what templates were rendered as part of a request: signals allow you to do exactly that.
与普通的处理器相比信号最大的好处在于你可以快速安全的订阅他们，这种临时的订阅方式 对于单元测试十分有用，例如当你想知道请求将调用哪个模板进行渲染时，通过信号机制你可以获 得你需要的答案。
Subscribing to Signals¶
To subscribe to a signal, you can use the
connect() method of a signal. The first
argument is the function that should be called when the signal is emitted,
the optional second argument specifies a sender. To unsubscribe from a
signal, you can use the
For all core Flask signals, the sender is the application that issued the signal. When you subscribe to a signal, be sure to also provide a sender unless you really want to listen for signals of all applications. This is especially true if you are developing an extension.
Here for example a helper context manager that can be used to figure out in a unittest which templates were rendered and what variables were passed to the template:
from flask import template_rendered from contextlib import contextmanager @contextmanager def captured_templates(app): recorded =  def record(sender, template, context): recorded.append((template, context)) template_rendered.connect(record, app) try: yield recorded finally: template_rendered.disconnect(record, app)
This can now easily be paired with a test client:
with captured_templates(app) as templates: rv = app.test_client().get('/') assert rv.status_code == 200 assert len(templates) == 1 template, context = templates assert template.name == 'index.html' assert len(context['items']) == 10
All the template rendering in the code issued by the application app in the body of the with block will now be recorded in the templates variable. Whenever a template is rendered, the template object as well as context are appended to it.
Additionally there is a convenient helper method
connected_to()). that allows you to
temporarily subscribe a function to a signal with is a context manager on
its own. Because the return value of the context manager cannot be
specified that way one has to pass the list in as argument:
from flask import template_rendered def captured_templates(app, recorded): def record(sender, template, context): recorded.append((template, context)) return template_rendered.connected_to(record, app)
The example above would then look like this:
templates =  with captured_templates(app, templates): ... template, context = templates
If you want to use signals in your own application, you can use the
blinker library directly. The most common use case are named signals in a
Namespace.. This is what is recommended
most of the time:
from blinker import Namespace my_signals = Namespace()
Now you can create new signals like this:
model_saved = my_signals.signal('model-saved')
The name for the signal here makes it unique and also simplifies
debugging. You can access the name of the signal with the
For Extension Developers
If you are writing a Flask extension and you to gracefully degrade for
missing blinker installations, you can do so by using the
If you want to emit a signal, you can do so by calling the
send() method. It accepts a sender as first
argument and optionally some keyword arguments that are forwarded to the
class Model(object): ... def save(self): model_saved.send(self)
Try to always pick a good sender. If you have a class that is emitting a
signal, pass self as sender. If you emitting a signal from a random
function, you can pass
current_app._get_current_object() as sender.
Decorator Based Signal Subscriptions¶
With Blinker 1.1 you can also easily subscribe to signals by using the new
from flask import template_rendered @template_rendered.connect_via(app) def when_template_rendered(sender, template, context): print 'Template %s is rendered with %s' % (template.name, context)
The following signals exist in Flask:
This signal is sent when a template was successfully rendered. The signal is invoked with the instance of the template as template and the context as dictionary (named context).
def log_template_renders(sender, template, context): sender.logger.debug('Rendering template "%s" with context %s', template.name or 'string template', context) from flask import template_rendered template_rendered.connect(log_template_renders, app)
This signal is sent before any request processing started but when the request context was set up. Because the request context is already bound, the subscriber can access the request with the standard global proxies such as
def log_request(sender): sender.logger.debug('Request context is set up') from flask import request_started request_started.connect(log_request, app)
This signal is sent right before the response is sent to the client. It is passed the response to be sent named response.
def log_response(sender, response): sender.logger.debug('Request context is about to close down. ' 'Response: %s', response) from flask import request_finished request_finished.connect(log_response, app)
This signal is sent when an exception happens during request processing. It is sent before the standard exception handling kicks in and even in debug mode, where no exception handling happens. The exception itself is passed to the subscriber as exception.
def log_exception(sender, exception): sender.logger.debug('Got exception during processing: %s', exception) from flask import got_request_exception got_request_exception.connect(log_exception, app)
This signal is sent when the request is tearing down. This is always called, even if an exception is caused. Currently functions listening to this signal are called after the regular teardown handlers, but this is not something you can rely on.
def close_db_connection(sender): session.close() from flask import request_tearing_down request_tearing_down.connect(close_db_connection, app)