Blinker Documentation

Blinker provides fast & simple object-to-object and broadcast signaling for Python objects.

The core of Blinker is quite small but provides powerful features:

  • a global registry of named signals

  • anonymous signals

  • custom name registries

  • permanently or temporarily connected receivers

  • automatically disconnected receivers via weak referencing

  • sending arbitrary data payloads

  • collecting return values from signal receivers

  • thread safety

Blinker was written by Jason Kirtand and is provided under the MIT License. The library supports Python 2.4 or later; Python 3.0 or later; or Jython 2.5 or later; or PyPy 1.6 or later.

Decoupling With Named Signals

Named signals are created with signal():

Every call to signal('name') returns the same signal object, allowing unconnected parts of code (different modules, plugins, anything) to all use the same signal without requiring any code sharing or special imports.

Subscribing to Signals

Signal.connect() registers a function to be invoked each time the signal is emitted. Connected functions are always passed the object that caused the signal to be emitted.

Emitting Signals

Code producing events of interest can Signal.send() notifications to all connected receivers.

Below, a simple Processor class emits a ready signal when it’s about to process something, and complete when it is done. It passes self to the send() method, signifying that that particular instance was responsible for emitting the signal.

Notice the complete signal in go()? No receivers have connected to complete yet, and that’s a-ok. Calling send() on a signal with no receivers will result in no notifications being sent, and these no-op sends are optimized to be as inexpensive as possible.

Subscribing to Specific Senders

The default connection to a signal invokes the receiver function when any sender emits it. The Signal.connect() function accepts an optional argument to restrict the subscription to one specific sending object:

This function has been subscribed to ready but only when sent by processor_b:

Sending and Receiving Data Through Signals

Additional keyword arguments can be passed to send(). These will in turn be passed to the connected functions:

The return value of send() collects the return values of each connected function as a list of (receiver function, return value) pairs:

Anonymous Signals

Signals need not be named. The Signal constructor creates a unique signal each time it is invoked. For example, an alternative implementation of the Processor from above might provide the processing signals as class attributes:

connect as a Decorator

You may have noticed the return value of connect() in the console output in the sections above. This allows connect to be used as a decorator on functions:

While convenient, this form unfortunately does not allow the sender or weak arguments to be customized for the connected function. For this, connect_via() can be used:

Optimizing Signal Sending

Signals are optimized to send very quickly, whether receivers are connected or not. If the keyword data to be sent with a signal is expensive to compute, it can be more efficient to check to see if any receivers are connected first by testing the receivers property:

Checking for a receiver listening for a particular sender is also possible:

Documenting Signals

Both named and anonymous signals can be passed a doc argument at construction to set the pydoc help text for the signal. This documentation will be picked up by most documentation generators (such as sphinx) and is nice for documenting any additional data parameters that will be sent down with the signal.

See the documentation of the receiver_connected built-in signal for an example.

API Documentation

All public API members can (and should) be imported from blinker:

from blinker import ANY, signal

Basic Signals

Named Signals

blinker.base.signal(name, doc=None)

Return the NamedSignal name, creating it if required.

Repeated calls to this function will return the same signal object. Signals are created in a global Namespace.

Blinker Changelog

Version 1.4

Released July 23, 2015

  • Verified Python 3.4 support (no changes needed)

  • Additional bookkeeping cleanup for non-ANY connections at disconnect time.

  • Added Signal._cleanup_bookeeping() to prune stale bookkeeping on demand

Version 1.3

Released July 3, 2013

  • The global signal stash behind blinker.signal() is now backed by a regular name-to-Signal dictionary. Previously, weak references were held in the mapping and ephermal usage in code like signal('foo').connect(...) could have surprising program behavior depending on import order of modules.

  • blinker.Namespace is now built on a regular dict. Use blinker.WeakNamespace for the older, weak-referencing behavior.

  • Signal.connect(‘text-sender’) uses an alterate hashing strategy to avoid sharp edges in text identity.

Version 1.2

Released October 26, 2011

  • Added Signal.receiver_connected and Signal.receiver_disconnected per-Signal signals.

  • Deprecated the global ‘receiver_connected’ signal.

  • Verified Python 3.2 support (no changes needed!)

Version 1.1

Released July 21, 2010

  • Added @signal.connect_via(sender) decorator

  • Added signal.connected_to shorthand name for the temporarily_connected_to context manager.

Version 1.0

Released March 28, 2010

  • Python 3.0 and 3.1 compatibility

Version 0.9

Released February 26, 2010

  • Added Signal.temporarily_connected_to context manager

  • Docs! Sphinx docs, project web site.

Version 0.8

Released February 14, 2010

  • Initial release

  • Extracted from flatland.util.signals

  • Added Python 2.4 compatibility

  • Added nearly functional Python 3.1 compatibility (everything except connecting to instance methods seems to work.)