circular import snafu

Gordon McMillan gmcm at hypernet.com
Thu Aug 10 08:52:29 EDT 2000


[posted and mailed]

Mookie D. wrote:

>Apologies if this is a rookie move, but I have looked for reasons why
>this may be happening and my trusty Python books and FAQ haven't solved
>it.
>
>I have several modules that by necessity are including each other in a
>circular manner.  Depending on which module I load first, I get
>different errors but always end in an error such as
>
>     ImportError: cannot import name MailList

>See below for the gory details.  I appreciate your suggestions for what
>I ought to be trying or doing differently, or HT debug this.

>Traceback (innermost last):
>  File "email.py", line 13, in ?
>    import mailboxMgr
>  File "/usr/lib/python1.5/ihooks.py", line 396, in import_module
>    q, tail = self.find_head_package(parent, name)

ihooks! That's not a rookie move!

>  File "/usr/local/dm/webapp/mailboxMgr.py", line 12, in ?
>    import email

First problem: Looks like your __main__ is email.py. When mailboxMgr 
imports email, it's getting a 2nd copy of email.py. Advice - create a top 
level script, say runner.py that says "import email; email.run()".
 
>  File "email.py", line 18, in ?
>    import dmpost

>  File "dmpost.py", line 29, in ?

That's an odd one - no source!

>  File "/home/mailman/Mailman/MailList.py", line 49, in ?
>    from webapp import subscription, dmconfig

This form of import is a problem in circular situations, because it can't 
complete until subscription and dmconfig are actually loaded. If you used:

import webapp.subscription
import webapp.dmconfig

then the import can complete as soon as webapp is available.

>  File "/usr/local/dm/webapp/subscription.py", line 16, in ?
>    import email

>  File "email.py", line 18, in ?
>    import dmpost

>  File "dmpost.py", line 29, in ?
>ImportError: cannot import name MailList

Don't know how dmpost imports MailList. If it's with "from", that's a 
problem. Another thing you can do is delay some of the imports. If 
"scrobble" if module A is the only place in A that module B is used, then 
you can use:

def scrobble(...):
  import B
  ...

The 2nd and subsequent times that "import" is hit, it won't do anything, 
(although it won't be free, either).

- Gordon



More information about the Python-list mailing list