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?
Singleton is a creational design pattern, which ensures that only one object of its kind exists and provides a single point of access to it for any other code. Singleton has almost the same pros and cons as global variables. Although they're super-handy, they break the modularity of your code.
Instance is an object that belongs to a class. For instance, list is a class in Python. When we create a list, we have an instance of the list class.
In object-oriented programming, a singleton class is a class that can have only one object (an instance of the class) at a time. After the first time, if we try to instantiate the Singleton class, the new variable also points to the first instance created.
The following are three ways to use singleton in Python.
Using metaclass
and decorator
to reach the goal.
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
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
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With