|  | Singleton implementation problems |  | |
| | | Urizev |  |
| Posted: Thu Jul 03, 2008 8:58 pm Post subject: Singleton implementation problems |  |
Hi everyone
I have developed the singleton implementation. However I have found a strange behaviour when using from different files. The code is attached.
Executing main new MySet object No singleton instance New singleton: <__main__.Singleton instance at 0x2b98be474a70> new MySet object There is a singlenton instance new Member new MySet object No singleton instance New singleton: <myset.Singleton instance at 0x2b98be474d88> new Member new MySet object There is a singlenton instance new Member new MySet object There is a singlenton instance
I do not know why, but it creates two instances of the singleton. Does anybody know why?
Regards |
| |
| | | Matthew Fitzgibbons |  |
| Posted: Thu Jul 03, 2008 9:11 pm Post subject: Re: Singleton implementation problems |  |
| |  | |
Urizev wrote:
| Quote: | Hi everyone
I have developed the singleton implementation. However I have found a strange behaviour when using from different files. The code is attached.
Executing main new MySet object No singleton instance New singleton: __main__.Singleton instance at 0x2b98be474a70 new MySet object There is a singlenton instance new Member new MySet object No singleton instance New singleton: myset.Singleton instance at 0x2b98be474d88 new Member new MySet object There is a singlenton instance new Member new MySet object There is a singlenton instance
I do not know why, but it creates two instances of the singleton. Does anybody know why?
Regards
------------------------------------------------------------------------
-- LINK
|
I've run into a similar problem. Basically, when you refer to a class from __main__ (i.e., the .py file you're actually running) versus from an imported module, Python doesn't realize they're the same class. Your Singleton implementation is creating one instance for __main__ and one for everything else. I'm sure there's someone around here who can say why Python behaves this way. You should be fine if you can restructure your code so you don't use your Singleton from __main__. In my case, I added a new main.py file.
-Matt |
| |
| | | George Sakkis |  |
| Posted: Fri Jul 04, 2008 1:15 am Post subject: Re: Singleton implementation problems |  |
| |  | |
On Jul 3, 6:58 pm, Urizev <uri...@gmail.com> wrote:
| Quote: | Hi everyone
I have developed the singleton implementation. However I have found a strange behaviour when using from different files. The code is attached.
Executing main new MySet object No singleton instance New singleton: __main__.Singleton instance at 0x2b98be474a70 new MySet object There is a singlenton instance new Member new MySet object No singleton instance New singleton: myset.Singleton instance at 0x2b98be474d88 new Member new MySet object There is a singlenton instance new Member new MySet object There is a singlenton instance
I do not know why, but it creates two instances of the singleton. Does anybody know why?
|
Because __init__() is called to initialize the state of an object *after* it has already been created. You should create a "new-style" class and define __new__() instead. Here's a working version:
class Singleton(object): # new-style class def __new__(cls, *args, **kwds): # return the singleton (if already created) try: return cls.__dict__['__singleton'] except KeyError: # raised only the first time for a given class # create the singleton and store it to the class namespace singleton = object.__new__(cls, *args, **kwds) setattr(cls, '__singleton', singleton) return singleton
class X(Singleton): def __init__(self, a): self.a = a
assert X(1) is X(2)
Note however that the classic Singleton pattern is usually frowned upon in Python; the preferred approach is to use (module level) globals. Also search for the "Borg pattern".
George |
| |
| | | Peter Otten |  |
| Posted: Fri Jul 04, 2008 3:56 am Post subject: Re: Singleton implementation problems |  |
| |  | |
Urizev wrote:
| Quote: | Hi everyone
I have developed the singleton implementation. However I have found a strange behaviour when using from different files. The code is attached.
Executing main
New singleton: __main__.Singleton instance at 0x2b98be474a70
New singleton: myset.Singleton instance at 0x2b98be474d88
I do not know why, but it creates two instances of the singleton. Does anybody know why?
|
Do you see it now I snipped the irrelevant output?
The problem is the structure of your program. The myset module is imported twice by Python, once as "myset" and once as "__main__". Therefore you get two distinct MySet classes, and consequently two distinct MySet.__instance class attributes.
Move the
if __name__ == "__main__": ...
statements into a separate module, e. g. main.py:
import myset import member
if __name__ == "__main__": print "Executing main" set1 = myset.MySet() set2 = myset.MySet()
mbr1 = member.Member() mbr2 = member.Member() mbr3 = member.Member()
Now main.py and member.py share the same instance of the myset module and should work as expected.
Peter |
| |
| | | Ben Finney |  |
| Posted: Fri Jul 04, 2008 5:12 am Post subject: Re: Singleton implementation problems |  |
Peter Otten <__peter__@web.de> writes:
| Quote: | The problem is the structure of your program. The myset module is imported twice by Python, once as "myset" and once as "__main__".
|
Yes, this is the problem. Each module imports the other.
| Quote: | Therefore you get two distinct MySet classes, and consequently two distinct MySet.__instance class attributes.
|
Are you sure? This goes against my understanding: that 'import foo' will not re-import a module that's already been imported, but will instead simply return the existing module.
So, I think if one evaluated 'myset is __main__', you'd find they are exactly the same module under different names; and therefore that there is only *one* instance of 'MySet', again under two names.
-- \ “Science doesn't work by vote and it doesn't work by | `\ authority.” —Richard Dawkins, _Big Mistake_ (The Guardian, | _o__) 2006-12-27) | Ben Finney |
| |
| | | Matthew Fitzgibbons |  |
| Posted: Fri Jul 04, 2008 5:52 am Post subject: Re: Singleton implementation problems |  |
Ben Finney wrote:
| Quote: | Peter Otten <__peter__@web.de> writes:
The problem is the structure of your program. The myset module is imported twice by Python, once as "myset" and once as "__main__".
Yes, this is the problem. Each module imports the other.
Therefore you get two distinct MySet classes, and consequently two distinct MySet.__instance class attributes.
Are you sure? This goes against my understanding: that 'import foo' will not re-import a module that's already been imported, but will instead simply return the existing module.
So, I think if one evaluated 'myset is __main__', you'd find they are exactly the same module under different names; and therefore that there is only *one* instance of 'MySet', again under two names.
|
You can see that they're distinct by checking the addresses (the instances in the OP also have different addresses). Besides, __main__ isn't imported normally.
-Matt |
| |
| | | Peter Otten |  |
| Posted: Fri Jul 04, 2008 6:33 am Post subject: Re: Singleton implementation problems |  |
| |  | |
Ben Finney wrote:
| Quote: | Peter Otten <__peter__@web.de> writes:
The problem is the structure of your program. The myset module is imported twice by Python, once as "myset" and once as "__main__".
Yes, this is the problem. Each module imports the other.
Therefore you get two distinct MySet classes, and consequently two distinct MySet.__instance class attributes.
Are you sure? This goes against my understanding: that 'import foo' will not re-import a module that's already been imported, but will instead simply return the existing module.
|
The main script is put into the sys.modules cache as "__main__", not under the script's name. Therefore the cache lookup fails.
| Quote: | So, I think if one evaluated 'myset is __main__', you'd find they are exactly the same module under different names; and therefore that there is only *one* instance of 'MySet', again under two names.
|
No:
$ cat tmp.py import tmp import __main__
print tmp is __main__
$ python tmp.py False False
Peter |
| |
| | | Terry Reedy |  |
| Posted: Fri Jul 04, 2008 6:37 am Post subject: Re: Singleton implementation problems |  |
| |  | |
Ben Finney wrote:
| Quote: | Peter Otten <__peter__@web.de> writes:
The problem is the structure of your program. The myset module is imported twice by Python, once as "myset" and once as "__main__".
Yes, this is the problem. Each module imports the other.
Therefore you get two distinct MySet classes, and consequently two distinct MySet.__instance class attributes.
Are you sure? This goes against my understanding: that 'import foo' will not re-import a module that's already been imported, but will instead simply return the existing module.
|
Peter is correct that a module can only be imported once per *name*. In 3.0b1 temp.py ================= print(__name__) import temp print(__name__) from sys import modules as m print(m['__main__'] is m['temp'])
produces ================== __main__ temp temp False __main__ False
Duplicate imports under multiple names are a known problem, and this is not the only way to create such. But what can an interpreter do when it sees 'import x' other than check that 'x' is not already a key in sys.modules? Iterate through sys.modules (increasingly slow as the dict grows) and do what exactly? The semantics of 'import x' are to get sys.modules['x'] if it exists; otherwise 'initialize' module x according to what that means for the implementation and current state and mode of operation of the system. Modules are not required to have .__file__ attributes since they do not have to come from named files . (And then the module is bound to 'x' in the importing namespace.)
Terry Jan Reedy |
| |
| | | Urizev |  |
| Posted: Sat Jul 05, 2008 7:31 pm Post subject: Re: Singleton implementation problems |  |
| |  | |
Great! Thanks everyone for so many references and comments. Lots of doubts have been solved.
On Fri, Jul 4, 2008 at 10:33 AM, Peter Otten <__peter__@web.de> wrote:
| Quote: | Ben Finney wrote:
Peter Otten <__peter__@web.de> writes:
The problem is the structure of your program. The myset module is imported twice by Python, once as "myset" and once as "__main__".
Yes, this is the problem. Each module imports the other.
Therefore you get two distinct MySet classes, and consequently two distinct MySet.__instance class attributes.
Are you sure? This goes against my understanding: that 'import foo' will not re-import a module that's already been imported, but will instead simply return the existing module.
The main script is put into the sys.modules cache as "__main__", not under the script's name. Therefore the cache lookup fails.
So, I think if one evaluated 'myset is __main__', you'd find they are exactly the same module under different names; and therefore that there is only *one* instance of 'MySet', again under two names.
No:
$ cat tmp.py import tmp import __main__
print tmp is __main__
$ python tmp.py False False
Peter -- LINK
|
-- Saludos
Juan Carlos
"Viva lo rancio!!" |
| |
|
|