Problem with modules refering to each other
Gordon McMillan
gmcm at hypernet.com
Sun Aug 8 11:17:10 EDT 1999
Phil Hunt writes:
> I have two python modules, both of which need to refer to classes
> defined in the other one. How do I do this?
>
> I am currently putting at the start of each module a line of the
> form:
>
> from theOtherModule import *
>
> However, this is not working. My modules -- greatly simplified --
> look like this:
>
> #bak.py
> from hhh import *
> ti = AnHhhClass()
> print ti
>
> and:
>
> #hhh.py
> from bak import *
> class AnHhhClass: pass
>
> When I run ``python bak.py'', I get the error message
> ``NameError: AnHhhClass''.
Plumbing rule #1: bak.py runs, Python hits the line with the "import"
statement, moves over to hhh.py. In hhh.py it hits the "import" line.
To protect itself against infinite recursion, it looks to see if
bak.py is being imported. In your case it's not, because what you
think of as "bak" is actually "__main__". So it starts importing bak
as a module. Hits the import line. Looks up hhh.py. This time it
detects recursion, so it just goes on, on the theory that whoever is
importing hhh.py will eventually complete the process. Which is true.
Plumbing rule #2: from module import ... doesn't do what you want. It
imports module, but not into your namespace. It takes what it finds
in the imported namespace and creates vars of the same name in your
namespace.
So when bak.py is imported, nothing has been bound into it's
namespace from hhh, because hhh's namespace is empty at that point.
Since the following line expects something from hhh to be bound into
bak.py's namespace, it fails.
So how do you fix this?
First, you never, ever use "from module import ..." unless (1)
the module has been specifically designed to allow this (see
what Tkinter or threading does to allow this) and (2) there are no
recursive imports going on.
Second, if you're doing recursive imports, you don't make any
references to items in the other module at the top level. They won't
be resolvable until the top level has been completely scanned.
Third, you remember that the script you run is not imported under
it's own name. It's in the import list, but as "__main__". Forgetting
this yields 2 copies of your module, and strange errors where vars
you set to new values don't change.
So bak.py should say:
import hhh
def doit()
it = hhh.AnHhhClass()
print it
And you should run a script that says:
import bak
bak.doit()
- Gordon
More information about the Python-list
mailing list