Singleton

Carl Banks pavlovevidence at gmail.com
Wed Oct 10 08:23:58 EDT 2007


On Oct 10, 5:36 am, pythoncuri... at gmail.com wrote:
> Hi,
>
> I've been trying to get some sort of singleton working in python, but
> I struggle a bit and I thought I'd ask for advice.
>
> The first approach was simply to use a module, and every variable in
> it will be seen by all who import the module.
> That works in some cases, but not if I have the following structure:
>
> one/
>   __init__.py
>   mod1.py
>   run.py
> two/
>   __init__.py
>   mod2.py
>
> run.py looks like this:
> #!/usr/bin/env python

Well, here's your problem.  Your main script is inside a package: that
is what's causing the namespace difficulties you're seeing.

I highly suggest you not do that.  A better ideas is to create a small
script in the project root that imports run.py, like this:

#!/usr/bin/env python
from one import run


[continuing with run.py]
> import mod1
> print mod1.number

It's is only tangentially related to your problem, but this usage is
deprecated.

Importing a file in the same package using "import modl" instead of
"from one import mod1" is called an impicit relative import (well,
actually in this case it isn't a relative import--more on that later--
but you seem to have intended it as a relative import).  Implicit
relative imports are scheduled to be removed from a future release of
Python.

You should use either an absolute import:

from one import mod1

Or an explicit relative import in Python 2.5 or above:

from . import mod1


See PEP 328.


[continuing again with run.py]
> import two.mod2
> print two.mod2.number
>
> mod1.py looks like this:
> import random
> number=random.randint(0,100)
>
> mod2.py looks like this
> import one.mod1
> number = one.mod1.number
>
> PYTHONPATH is set to the directory containing the 'one' and 'two'
> directories.
>
> Now when I run the 'run.py', it will print two different numbers.
> sys.modules tells me that 'mod1' is imported as both 'one.mod1' and
> 'mod1', which explains the result.

Here's the problem: the main script is NOT executed within the package
"one".  A file's presence in a package directory is not sufficient for
it to be part of the package: you actuatlly have to import the file
through that package.

When you ran run.py, the Python interpreter did not import the file
via the "one" package.  It loaded the file, compiled it, and ran it,
but as a standalone file, not as part of a package.

Then, when you imported "mod1" from "run.py", it only saw that mod1.py
was a file in the same directory.  So it imported it as a regular
module, not a submodule of a package.

Now, when mod2 imported mod1, it went through the package "one" to
import it.  Therefore, it considered mod1 to be part of the package
"one", and so imported it as a submodule of "one".


> Looking at:http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52558
> I find a singleton class, but it has the same problem. If it's
> imported in two different ways, I have not a singleton but a ...
> 'doubleton' or something.
>
> It is possible to solve this by always importing with the complete
> path like 'one.mod1', even when inside the 'one' directory, but that's
> an error waiting to happen.

I've been doing it for a few years; I haven't had a problem.  If
you're concerned, you can add "from __future__ import
absolute_imports" to your files to catch any lapses.


> So how do people solve this? Is there an obvious way that I missed?
>
> I'm thankful for any advice you might provide.

Just keep your main scripts out of the package directories and you'll
be fine.



Carl Banks




More information about the Python-list mailing list