Here's a quite complete Singleton mixin class for Python, including such niceties as thread safety for singleton creation. Public domain. Based in part on ideas I found on this wiki page, followed by a substantial number of enhancements based on comments posted below and based on my own additional needs. If you find it useful and think of ways to improve it, please post a comment here.
Lately I've noticed some discussion of the evilness of singletons. One poster says:
It's almost impossible to subclass a Singleton, and if you manage it, then you shouldn't have been using a Singleton in the first place. You don't *even* want to go there. I've walked roads that I dare not recount. Just pretend you can't do it, and you'll save yourself amazing amounts of pain.
My singleton mixin source includes unit tests showing that at least rudimentary subclassing does work with the approach used here. I haven't run into any problems in real life either, although I use singletons sparingly.
If anyone has examples or thoughts about problems with subclassing with this mixin, please post a comment.
Update, July 28, 2009: Now optionally allows multiple calls to getInstance() which all include arguments. See the docstring for more. Update, July 27, 2009: I try to keep the Singleton version here in sync with our svn version, so that any enhancements or fixes will be included. The code, still at the original link (above), has been modified today to add thread safety for singleton creation, and also incorporates ideas from some of the recent comments people have posted here. In particular, singleton construction can now handle keyword arguments.
Here's one from Michele Simionato that uses metaclasses:
class Singleton(type):
def __init__(cls,name,bases,dic):
super(Singleton,cls).__init__(name,bases,dic)
cls.instance=None
def __call__(cls,*args,**kw):
if cls.instance is None:
cls.instance=super(Singleton,cls).__call__(*args,**kw)
return cls.instance
#example:
class C:
__metaclass__=Singleton
Posted by: Doug | March 11, 2004 at 05:31 PM
That's really interesting! I haven't used metaclasses yet. I'm going to look them up for the first time because of the above comment. I may have more to say after I do...
Posted by: Gary Robinson | March 12, 2004 at 04:01 PM
I now use metaclasses in my singleton class, still linked to at the same link. They help!
Posted by: Gary Robinson | June 08, 2004 at 05:13 PM
Not a sw engineer myself but think that this example of Singleton is very neat:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531
Posted by: Lorenzo | September 27, 2004 at 01:43 PM
Hey, that _is_ really neat. Thanks for pointing it out. I don't have time now to consider its pros and cons in depth re more traditional singletons. I'll probably add a comment here when I do. In the meantime, I suggest anyone who is looking for a singleton and ends up on this page to check out the link posted in the previous comment. It really refers to the so-called "Borg" pattern, which not really a standard Singleton, but more of an alternative to a Singleton.
Posted by: Gary Robinson | September 27, 2004 at 03:43 PM
I do have one reflection now. I think that using the Borg pattern is less self-documenting than using the Singleton pattern, and not only because it is different from what people think of when they think of the properties of a Singleton, but also because it creates Python objects that don't work the way Python objects normally work (they don't normally share state).
I think those objections could be worked around in an actual program by using a standard naming convention for Borg classes, supplying documentation, and making sure everyone understands it. Whether it would be worth it or not, I don't know.
Posted by: Gary Robinson | September 28, 2004 at 09:37 AM
With Gary's permission I have begun using his code in an embryonic accounting package (http://sourceforge.net/projects/transactionsafe). The simplicity of using it for my classes impressed me no end, and so far it has made the development of this week's release easier.
I'm a very new python user, and the main thing that scared off the borg pattern was that I couldn't work out how to ensure the object state was initialised only once. In my case I have singletons depending on other singletons to provide a data model for the application and an observer pattern set-up between them. This singleton pattern was easy to integrate with my code and to understand the rammifications of.
Benjamin.
Posted by: Benjamin Carlyle | September 28, 2004 at 10:31 AM
One note, nobody needs my permission to use singletonmixin.py, which benefited from a lot of input from other people. (I would appreciate it, though, if you provide a link to this Web page and a comment here if you use it, however!)
I'm glad you are finding it useful, Benjamin!
Posted by: Gary Robinson | September 28, 2004 at 11:04 AM
Gary:
I want to use your singleton class to build a DB object, but I'm not so sure how to do it. Is it possible? If it is, could you please provide an example of how doing this (when you have some time of course). Thanks.
Regards, Douglas
Posted by: Douglas | December 30, 2004 at 07:21 AM
Hi Gary. While this looks like the most well thought out Singleton implementation I've found in Python, I'm having trouble making it work. To wit:
Python 2.3.4 (#2, Jan 5 2005, 08:24:51)
[GCC 3.3.5 (Debian 1:3.3.5-5)] on linux2
>>> from singletonmixin import Singleton
>>> class Foo(Singleton):
... pass
...
>>> m = Foo.getInstance()
Traceback (most recent call last):
File "", line 1, in ?
File "singletonmixin.py", line 78, in getInstance
if len(lstArgs) != cls._getConstructionArgCountNotCountingSelf():
File "singletonmixin.py", line 91, in _getConstructionArgCountNotCountingSelf
return cls.__init__.im_func.func_code.co_argcount - 1
AttributeError: 'wrapper_descriptor' object has no attribute 'im_func'
>>>
I don't understand the inner workings of metaclasses well enough to quickly fix this, so could you shed some light on what the problem might be?
Thanks!
Steve Freitas
Posted by: Steve Freitas | January 17, 2005 at 03:30 PM
I hadn't thought about this earlier, but it looks like you need to have a constructor for your class, even if that constructor is empty. The following version works with no problems:
Posted by: Gary Robinson | January 17, 2005 at 03:41 PM
Hi,
I really like this implementation!!
About the lstArgs in getInstance, it seems it doesn't handle defaults :(
I wonder if anyone has a solution for it, or should I get rid of the error checking?!?!
I found out I can check the amount of defaults with .im_func.func_defaults, but then the number of args can vary, what makes it more complicated...
Posted by: Michal Eldar | May 17, 2005 at 06:31 PM
Thanks Michal for pointing this out. It's fixed in the latest version, uploaded today.
Posted by: Gary Robinson | May 31, 2005 at 04:21 PM
Hey,
I found your singleton really useful, but I made some modifications to it. Biggest is that I made getInstance ignore its args if the object was already constructed (rather than throw an exception saying "It's already constructed, your arguments are meaningless"). The reason is because in this application, I'm unable to construct the object until late in the program, and I didn't want to have to check in the main code whether the singleton had already been instantiated, and pass args accordingly. (Note that there's no public way to check if the thing has been instantiated anyhow.)
Secondly, I changed the MetaSingleton.__call__ function to just delegate the call to cls.getInstance, in other words, re-enabled the S() constructor. At this point, getInstance already takes arguments, so it behaves pretty much like a constructor anyhow. I, the developer, knew that I was using a singleton in these situations, and thought it was silly to force use of one function to construct/get an instance versus another.
Thanks again.
Ethan
Posted by: Ethan Glasser-Camp | August 02, 2005 at 03:41 PM
Hi Gary, we're now using the singleton mixin in our internal VR code, espace - and the key reason is that it comes with unit tests ;-) Thanks for releasing this little gem with no strings atttached. I'll buy you a beer if we ever meet up.
Posted by: Darran Edmundson | May 08, 2006 at 02:22 AM
Gary,
Thanks for posting this nice singleton code-- it's exactly what I needed for a project I am working on.
I did have to modify the code: I had a class with a keyword default argument in the constructor getInstance() didn't work. I used the im_func.func_defaults trick posted above.
Thanks again,
Marcus
Posted by: Marcus Goldfish | June 25, 2006 at 08:03 PM
Is this broken in Python 2.5? PyDev is flagging it with errors and I'm having trouble getting it to work.
Posted by: Gordon Morehouse | March 12, 2007 at 12:56 AM
Thanks for your work! Now let's see how you'll interact with all the junk coming from social blogs, social networks, social software and the whole good load from web 2.0 ;) Tough luck on that!
Posted by: DDT-WEBKINZ | October 22, 2007 at 08:42 PM
Thanks for this great utility. I ran into a problem with it since I have a class that takes keyword args, and the arity check was failing. I've updated the code to handle this case by taking both *args and **kwargs and invoking __init__ with them. This changes the exception that is raised when the specified args aren't sufficiently specified, so the unit test also changed to reflect that.
Posted by: Lonnie Hutchinson | July 22, 2009 at 12:07 PM
Thanks Lonnie, Michal, and Marcus for mentioning the issue with keyword arguments, and especially to Lonnie for posting code!
The final version takes most of Lonnie's changes, but still checks to make sure that necessary args are included in the instantiating call to getInstance() by raising a SingletonException. It does this by checking for the TypeError Lonnie put into the unit test, but additionally checking the exception message to see if it corresponds to the missing arguments error. (A different technique than Michal and Marcus used.)
I'll mention here something I mentioned also in the update to the main post: the code now should be threadsafe for singleton creation. Of course your Singleton class may not itself be threadsafe; I can only control the creation!
Posted by: Gary Robinson | July 27, 2009 at 10:43 PM
Made an additional update to deal with Ethan's issue where he wanted to be able to call getInstance() multiple times with args, where the args are ignored in calls other than the first. To enable this functionality, just include
ignoreSubseqent = True
in the class definition.
Posted by: Gary Robinson | July 28, 2009 at 08:41 AM
Here is my favorite singleton implementation. It serves me quite well and is fluidly heritable:
Posted by: James Stroud | October 29, 2009 at 12:43 AM
Inspired by your design I've created a decorator based approach.
I was unable to find [code] tags here, so please see
http://pastebin.com/f7834050
Posted by: Jan Bessai | November 26, 2009 at 04:21 PM
Please see
http://pastebin.com/f66169fef
for an updated version that comes in more handy for subsequent constructor calls and is transparent for docstrings.
Posted by: Jan Bessai | November 26, 2009 at 05:48 PM
Just thank you Gary! :)
Posted by: Ivan Ricotti | May 14, 2010 at 10:35 AM