29 Kasım 2008 Cumartesi

Singleton Pattern in Python

The Singleton actually is not something very different or new invention. The purpose of it is to have only a single instance of some class so you can have a global point of access which is cool. For now i think i can use it for configuration manager classes, some cool loggers and some context variables. Maybe i will find more of em. The Singleton pattern is a little bit different from one that is in Java. In Java to make a singleton you have to make your constructor private and have some static method to do the instance initialization. In python what you have todo is override the __new__ method of the Singleton candidate. There are lots of examples on the net related with that topic so you can search one before use mine. Actually mine is not written or thought by me i found it also (from aspn CookBook site) :)

Here is the first version i found and think is good : LINK
As you will see there is some time and sleep things in it , i put em there to test what happens when some threaded classes use it. And as you may imagine some of the threads got different references of that Class. Here is the Thread i used :


from threading import *
import time
import thread

class ThreadSingleton(Thread):
"""
A simple thread to work on that
"""
def __init__(self,id):
Thread.__init__(self)
self.id = id

def run(self):
"""
Here initialize the singleton
"""
self.s=Singleton()

print "Im thread %d and %d"%(self.id,id(self.s))
time.sleep(2)

def get_singleton(self):
return id(self.s)



Here is the code that tests it :

def singleton(t="threaded"):
for j in range(100):
threads = []
for i in range(10):
if t!="threaded":
threads.append(ThreadSingleton(i))
else:
threads.append(RealThreadedSingleton(i))

for i in threads:
i.start()

for i in threads:
i.join()

print "The final ids are :"
t0 = threads[0]

for i in threads:
assert t0.get_singleton() == i.get_singleton()

t0.s.destroy()


if j%10 == 0:
print "************** %d COMPLETED **********"%j



After those tests i got some Assertion Errors because some of the threads got different references of the object. What we know from here is that our Singleton is not thread-safe and we should fix it. Here is the threaded version of the Singleton LINK :

To test that new verison i nedded some new ThreadClass to call the new created Singleton :


class RealThreadedSingleton(ThreadSingleton):

def run(self):
"""
Here initialize the singleton
"""
self.s=ThSingleton()

print "Im thread %d and %d"%(self.id,id(self.s))
time.sleep(2)



After final changes i run the tests 1000 times and didnt have any problems. Why we should bother to have Singleton threa-safe , because i'm going to use it in some frameworks that uses threads heavily, so icant be sure when that one will be called. To conclude, when write some cool classes always should think the posibility of theraded usages.

3 yorum:

Adam Olsen dedi ki...

The singleton pattern is grossly overrated. Just use a global and document the class as private (ie put a leading underscore in the name).

makkalot dedi ki...

Well it is one of the ways to do things, as you know in programming there is no one way to do the stuff (especially in Python). I have seen the Singleton pattern in lots of open source projects, but didnt use it yet :) Btw, thanks for the comment.

Adsız dedi ki...

Your blog keeps getting better and better! Your older articles are not as good as newer ones you have a lot more creativity and originality now keep it up!