The singleton pattern ensures a class has exactly one instance and provides a global point of access to it. In languages like Java, implementing a singleton requires private constructors, static methods, and thread-safety considerations. Python's module system makes the pattern much simpler, and in many cases you do not need a class at all.
This article covers the Pythonic approaches to singletons, from the module-level pattern you should use most of the time to the class-based approach for when you need more control. It builds on the module design principles from designing reusable Python modules.
Modules are singletons
The most Pythonic singleton is a module. When Python imports a module, it executes it once and caches the result in sys.modules. Every subsequent import in any file retrieves the same module object. This is exactly what a singleton provides, without any special code.
A configuration manager using a module needs no class at all. Module-level variables hold the shared state:
# config.py
_settings = {}
_loaded = False
def load(path):
global _settings, _loaded
with open(path) as fh:
_settings = json.load(fh)
_loaded = True
def get(key, default=None):
return _settings.get(key, default)
def is_loaded():
return _loadedEvery file that needs configuration imports the module. All importers share the same _settings dictionary. If one part of the application calls config.load(), every other part sees the loaded data immediately.
The class-based singleton with new
When you need a class with inheritance, lazy initialization, or a formal interface that tools can check, use a class with __new__ to enforce single instance creation:
class DatabasePool:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self, connection_string=None):
if self._initialized:
return
self.connection_string = connection_string
self._connections = []
self._initialized = True
def get_connection(self):
conn = self._create_connection()
self._connections.append(conn)
return connThe __new__ method ensures only one instance exists. The __init__ method uses a guard to avoid reinitializing the instance on subsequent calls. A caller writes pool = DatabasePool("postgresql://...") and always receives the same object.
This approach is useful when you need to subclass the singleton for testing. A test can create a MockDatabasePool that inherits from DatabasePool and overrides connection creation without affecting the production code. For a broader look at when the singleton fits alongside other patterns, see Common Design Patterns in Python.
Thread-safe singletons
The class-based approach above is not thread-safe. Two threads calling DatabasePool() simultaneously could both see _instance is None and create two instances. Add a lock to prevent this:
import threading
class DatabasePool:
_instance = None
_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instanceThe double-checked locking pattern acquires the lock only when the instance might need creation. After creation, subsequent calls skip the lock entirely.
For most applications, the module-level approach avoids threading concerns entirely because module imports are thread-safe in Python. The import system handles the locking for you.
When modules beat classes
A module is the right choice when your singleton manages shared state without complex behavior. Configuration, caches, connection pools, and loggers all fit this pattern. The syntax is familiar, the import system handles thread safety, and there is no boilerplate.
A class is the right choice when you need inheritance for testing, when the singleton must conform to a Protocol or ABC for type checking, or when lazy initialization matters because creating the instance is expensive.
If you are unsure, start with a module. It is trivial to upgrade to a class later if requirements change. Going the other direction, from a class with new tricks back to a simple module, is harder because callers have already coupled to the class interface.
Rune AI
Key Insights
- Python modules are singletons by default: imported once, shared by all importers.
- Use module-level variables for configuration, caches, and shared state.
- A class-based singleton with new works when you need inheritance or lazy init.
- Avoid over-engineering; a module is often the simplest and most Pythonic solution.
Frequently Asked Questions
Does Python have a built-in singleton?
When should I use a singleton in Python?
Conclusion
Python modules are the most natural singleton. Before writing a class with new tricks or metaclasses, ask whether a module with a few functions and module-level variables solves the same problem with less code. Reach for a class-based singleton only when you need inheritance, lazy initialization, or a formal interface.
More in this topic
How to Test Python Code
Learn what testing means in Python, the core ideas behind automated tests, and the built-in and third-party tools that make testing practical.
Write Your First Python Unit Test
Write and run your first Python unit test step by step, using unittest to check a small function and understand the test output.
The Factory Pattern in Python
Learn how to use the factory pattern in Python to encapsulate object creation, making your code more flexible and easier to extend.