0

I've tried recently to add a singleton to my project, but it doesn't act like I'd think it would. The code looks somewhat like this:

main/main.py

class main(metaclass=Singleton):
    def __init__(self):
        ....
    def Action(self):
        self.helper=otherclasses.other.other()

if __name__ == "__main__":
    m = main()
    m.Action()

main/metaclasses/singleton.py

class Singleton(type):
    _instance = None
    def __init__(cls, name, bases, dict):
        super(Singleton, cls).__init__(name, bases, dict)

    def __call__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instance 

    def Instance(cls, *args, **kwargs):
        return cls.__call__(*args, **kwargs)

main/otherclasses/other.py

class other():
     def __init__(self):
         ...
         self.main = Main.Instance()
         ...

so, as far as I understand this concept - I should have got the same instance of Main for subclass. Yet I get a whole new Main object. I'd be glad for some help! What am I missing?

Thanks in advance.

Wombatz
  • 4,958
  • 1
  • 26
  • 35
John M
  • 1
  • 4
  • How did you find out that `Main.Instance()` returns a new object? Also why is `subclass` called subclass when it is not a subclass? – Wombatz Jan 31 '16 at 23:49
  • Main prints logs in it's __init__ function, which are being printed again whenever I call it from otherclass Also, subclass isn't called subclass, I've named it that for this post only. Bad name choosing, edited – John M Feb 01 '16 at 06:26
  • You must have changed something else when copying your code to this question. I copied it (changing lowercase `singleton` to uppercase) and every attempt at instanciating `main` or calling `main.Instance()` resulted in the exact same object. Oh and i also indented `singleton.py` correctly` – Wombatz Feb 01 '16 at 07:29
  • Well, I've fixed it and posted an answer. I guess you've ran it appropriately and not through "main.py" as I did, thus it worked for you. Thanks for your help! – John M Feb 01 '16 at 21:04

1 Answers1

0

Solved it.

I believe that the reason for the problem was that I ran the program through "# python main.py". This way, because main.py wasn't loaded as a module, when other.py called "import main", it was re-loaded, and thus Main re-initialized Singleton.

Moving the "Run" function to another file ("# python Run.py") and importing main.py from there, thus only initializing Singleton (and Main) only once as I wanted to.

Thank you all :)

John M
  • 1
  • 4
  • `python main.py` runs `main.py` as a module: the `__main__` module. I'm not sure how you did it thoug. You ran `python main.py` and `other.py` imported main? How is that possible? Also no module will be re-loaded, they are all cached. – Wombatz Feb 02 '16 at 08:34
  • By reading sys.modules I could see that in running `python main.py` I get `Main` twice: once from `__main__` and one from `main.py`. By moving it out to `python run.py`, I only got it once. About `other.py` importing main: I need main to dynamically load modules from some source, using `importlib.import_module(mod)`. This way, when `other.py` imports main - it doesn't re-import itself and crash. – John M Feb 03 '16 at 20:23