19

I am creating a Python application that includes socket communication with a server. I would like to have a module which can be used throughout my entire application (several other modules). Currently my module look like this:

class SocketCommunication:

    def __init__(self):
        self.socketIO = SocketIO(settings.ADDRESS, settings.PORT, Namespace)

    def emit(self, message, data):
        json_data = json.dumps(data.__dict__)
        self.socketIO.emit(message, json_data)


class Namespace(BaseNamespace):
    def on_connect(self):
        print '[Connected]'

    def on_disconnect(self):
        print "[Disconnected]"

When I use this in other modules I do the following:

import SocketCommunication
self.sc = SocketCommunication()

The problem is that every time I do this, a new connection is created which will be displayed as a new client on the server, and that is undesirable. From what I can read, Singletons should be avoided in Python and therefore I am curious about what is best practice for this type of problem?

user3170354
  • 391
  • 1
  • 4
  • 11
  • 2
    Read about the **_The Borg Design Pattern_** [here](http://code.activestate.com/recipes/577870-singleton-we-dont-need-no-stinkin-singleton-the-bo/) and [here](http://code.activestate.com/recipes/66531/) for an easy ways to convert a class into a singleton. There are other ways, as well. – martineau Feb 14 '17 at 23:07
  • 1
    I'd use the class itself as a singleton. I never had problems with this approach. – Alfe Feb 14 '17 at 23:19
  • The `import SocketCommunication` you say you do in the other modules wouldn't work because `SocketCommunication` is the name of one of your classes. It would need to be something like `from my_module import SocketCommunication` in order for the next line to be valid. That said, you could effectively make the class a singleton adding `SocketCommunication = SocketCommunication()` in `my_module.py` file after the class is defined. That way it will be very difficult to create any more instances because the class name will have be overriden with an instance of itself. – martineau Feb 15 '17 at 00:04

2 Answers2

26

The following are three ways to use singleton in Python. Using metaclass and decorator to reach the goal.

  1. use __new__

     class Singleton(object):
         def __new__(cls, *args, **kw):
             if not hasattr(cls, '_instance'):
                 orig = super(Singleton, cls)
                 cls._instance = orig.__new__(cls, *args, **kw)
             return cls._instance
    
     class MyClass(Singleton):
         a = 1
    
     one = MyClass()
     two = MyClass()
    
     two.a = 3
     print one.a
     #3
     print id(one)
     #29097904
     print id(two)
     #29097904
     print one == two
     #True
     print one is two
     #True
    
  2. use __metaclass__

class Singleton2(type):
    def __init__(cls, name, bases, dict):
        super(Singleton2, cls).__init__(name, bases, dict)
        cls._instance = None

    def __call__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = super(Singleton2, cls).__call__(*args, **kw)
        return cls._instance


    class MyClass2(object):
        __metaclass__ = Singleton2

    one = MyClass2()
    two = MyClass2()

    two.a = 3
    print one.a
    #3
    print id(one)
    #31495472
    print id(two)
    #31495472
    print one == two
    #True
    print one is two
    #True
  1. use decorator

      def singleton(cls, *args, **kw):
         instances = {}
         def _singleton(*args, **kw):
            if cls not in instances:
                 instances[cls] = cls(*args, **kw)
            return instances[cls]
         return _singleton
    
     @singleton
     class MyClass3(object):
         a = 1
         def __init__(self, x=0):
             self.x = x
    
     one = MyClass3()
     two = MyClass3()
    
     two.a = 3
     print one.a
     #3
     print id(one)
     #29660784
     print id(two)
     #29660784
     print one == two
     #True
     print one is two
     #True
     one.x = 1
     print one.x
     #1
     print two.x
     #1
    

I prefer to use decorator.

Shubhank Gupta
  • 705
  • 2
  • 10
  • 27
caimaoy
  • 1,148
  • 1
  • 11
  • 25
  • 1
    The decorator arguments `*args` and `**kwargs` should be inputs to the `_singleton` method, rather than the `singleton` class, no? – khosrow Feb 18 '21 at 21:04
  • Also a caveat with the decorator solution may be that if you have class variables, this singleton will replace the class with a function, and access to that variable via `MyClass.CLASS_VAR` will be lost. – khosrow Feb 18 '21 at 21:06
4

Singletons are controversial because they're often used as a way to wrap up global variables. This is why some people advocate for their avoidance. Globals make testing harder, they limit access control, and often lead to strong coupling between variables. (see http://wiki.c2.com/?GlobalVariablesAreBad for more details as to why globals are generally bad practice)

In your particular scenario, using a singleton is most likely appropriate because you are simply trying to stop SocketCommunication being initialised multiple times (for good reason), rather than trying to use it as a container for a global state.

See Are Singletons really that bad? and What is so bad about singletons? for some discussion on Singletons.

Community
  • 1
  • 1
ToxicTeacakes
  • 1,124
  • 1
  • 10
  • 19
  • Thanks for your answer. It seems that in this particular case, a singleton is the best solution when I only need a single instance of the class. – user3170354 Feb 16 '17 at 17:22