Re: Singleton implementation problems

Discussion in 'Python' started by Peter Otten, Jul 4, 2008.

  1. Peter Otten

    Peter Otten Guest

    Urizev wrote:

    > 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
     
    Peter Otten, Jul 4, 2008
    #1
    1. Advertising

  2. Ben Finney wrote:
    > Peter Otten <> 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
     
    Matthew Fitzgibbons, Jul 4, 2008
    #2
    1. Advertising

  3. Peter Otten

    Peter Otten Guest

    Ben Finney wrote:

    > Peter Otten <> 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
     
    Peter Otten, Jul 4, 2008
    #3
  4. Peter Otten

    Terry Reedy Guest

    Ben Finney wrote:
    > Peter Otten <> 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
     
    Terry Reedy, Jul 4, 2008
    #4
  5. Peter Otten

    Urizev Guest

    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 <> wrote:
    > Ben Finney wrote:
    >
    >> Peter Otten <> 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
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >




    --
    Saludos

    Juan Carlos

    "¬°¬°Viva lo rancio!!"
     
    Urizev, Jul 5, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Proton Projects - Moin

    Singleton - Whether Cloneable overrides Singleton

    Proton Projects - Moin, Mar 26, 2007, in forum: Java
    Replies:
    4
    Views:
    3,285
    Proton Projects - Moin
    Mar 27, 2007
  2. Wilhelm
    Replies:
    1
    Views:
    172
  3. Trans
    Replies:
    12
    Views:
    284
    Robert Klemme
    Sep 14, 2007
  4. Paul McMahon
    Replies:
    3
    Views:
    210
    David A. Black
    Jun 9, 2008
  5. Charles Oliver Nutter

    Singleton methods without the singleton class

    Charles Oliver Nutter, Mar 15, 2010, in forum: Ruby
    Replies:
    4
    Views:
    212
    Charles Oliver Nutter
    Mar 22, 2010
Loading...

Share This Page