Implementing Interpreter-Wide Objects in Python
Several patterns for sharing mutable state across Python modules, illustrated by Tornado options and the standard logging module.
Sometimes an object should be shared by every module in a Python interpreter. Importing a module already provides one shared module object, so a mutable object created at module scope can act as interpreter-wide state.
Tornado’s options system follows this pattern: the module exposes functions such as define, while the actual values live in a shared options object. Every importer works with the same instance because Python caches imported modules in sys.modules.
The standard logging package uses a related design. Calls to logging.getLogger(name) are coordinated through a manager whose loggerDict stores logger instances by name. Repeated calls therefore return the same logger. The implementation also uses locks because creating and registering shared objects must be safe when several threads call it concurrently.
For application code, a small dedicated module containing one explicitly named instance is usually clearer than a complicated singleton. When lazy creation or subclass control is required, keep the registry and its locking behavior visible rather than hiding global state behind surprising magic.