Reputation: 7486
Given two modules, main and x with the following contents:
main:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
cls._instance.x = 10
return cls._instance
uvw = Singleton()
if __name__ == "__main__":
print(id(uvw))
uvw.x += 10
print(uvw.x)
import x
and x, respectively:
import main
print(id(main.uvw))
print(main.uvw.x)
I would now expect that executing main would yield the same IDs and the value twenty in both instances, but what I get is this:
$ python main.py
140592861777168
20
140592861207504
10
Is there any way I can ensure that uvw
is the same object at both places?
Upvotes: 13
Views: 7682
Reputation: 7486
I found out that the problem is that main
is loaded twice when it's executed from the command line, one time as __main__
and the second time when imported by x as main
.
I found a very evil hack to circumvent the second load:
sys.modules["main"] = sys.modules["__main__"]
Separating the main module and the singleton class is not favorable in my case.
Upvotes: 1
Reputation: 3643
Python loads each module by name once (unless reload(module)
is called). If you run main.py
, the module is __main__
(try printing uvw.__class__.__module__
). When x
imports main
, the module called main
is being loaded for the first time.
If you defined uvw
in a third module, or in x
-- as long as it is imported in the same way into __main__
and x
-- it would be the same object.
Upvotes: 7
Reputation: 97591
I reckon the problem is that your Singleton
class is somehow being reloaded, and thus loses its _instance
field in the second module.
I think this will work:
singleton.py
:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
cls._instance.x = 10
return cls._instance
a.py
:
from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)
b.py
:
from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)
main.py
import a
import b
Upvotes: 8