Python: thread-safe implementation of a singleton

Boris HUISGEN March 23, 2019

development python



Sometimes the singleton design pattern is required to limit resources usage like the number of connections to a database or an external service.

In other languages this design pattern could be difficult to write I mean specifically to satisfy the thread safety but for Python it’s not really the case. Here is my implementation.

Implementation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    import logging
    import threading
    
    
    class MySingleton(object):
        _instance: object = None
        _lock: threading.Lock = threading.Lock()
    
        def __new__(cls):
            """Create a new instance"""
            if MySingleton._instance is None:
                with MySingleton._lock:
                    if MySingleton._instance is None:
                        MySingleton._instance = super(MySingleton, cls).__new__(cls)
                        MySingleton._instance._initialized = False
    
            return MySingleton._instance
    
        def __init__(self):
            """Initialize the instance"""
            if self._initialized is False:
                self._logger = logging.getLogger(self.__class__.__name__)
                self._count = 0
    
                self._initialized = True                
            
            self._logger.debug("using instance: %s" % self._instance)
            
        def increment(self):
            """Increment the counter"""
            self._count += 1
                                    
            self._logger.debug("count = %d" % self._count)

Test

To prove that it works let’s try with the python console:

    $ python
    >>> from code import MySingleton
    >>> logging.basicConfig(level=logging.DEBUG, handlers=[logging.StreamHandler()])
    >>> a = MySingleton()
    DEBUG:MySingleton:using instance: <__main__.MySingleton object at 0x7f8bee80c550>
    >>> b = MySingleton()
    DEBUG:MySingleton:using instance: <__main__.MySingleton object at 0x7f8bee80c550>
    >>> a.increment()
    DEBUG:MySingleton:count = 1
    >>> a.increment()
    DEBUG:MySingleton:count = 2
    >>> b.increment()
    DEBUG:MySingleton:count = 3

See also

Boto : gérer le logging
Read more
Let’s Encrypt : générer un certificat wildcard
Read more
NetworkManager : configuration d’une interface dummy
Read more