FAQ 1.7.3 : How can I have modules that mutually import each other

John Roth newsgroups at jhrothjr.com
Sun Mar 20 18:32:59 EST 2005


Circular import dependencies don't work well; depending
on the exact conditions they can leave you pulling your  hair
out for hours. In your example, just pull the global variable
out into a third module and have both of your major
modules import and reference it from there.

In general, you should never have circular imports at
load time. There are three general ways of handling
the issue:

1. Redesign to eliminate the circular dependencies.
2. Put the classes with the circular dependencies in
   the same module.
3. Load the backlinks at run time.

I may be old fashioned, but I put all of the import
statements at the top of the module. Putting them
into the middle of functions obscures the structure
of the code, at least to my eyes. I'd rather have them
all in one place.

I've got a Java package (Fit Library) that I'm porting
to Python that has a number of very nasty circular
import dependencies that I can't structure out easily:
they're fundamental to the functionality. I'm taking
the "load at run time" option, which works well since
the basic FIT package has a very competent dynamic
loader.

However, all of this is kind of advanced functionality.
Most applications don't require that kind of mess.

John Roth








"MackS" <mackstevenson at hotmail.com> wrote in message 
news:1111262718.157993.179100 at g14g2000cwa.googlegroups.com...
> Hi
>
> I'm new to Python, I've read the FAQ but still can't get the following
> simple example working:
>
> # file main_mod.py:
>
> global_string = 'abc'
>
> def main():
>
>    import auxiliary_mod
>    instance = auxiliary_mod.ClassA()
>    instance.fun()
>    return
>
> main()
>
> # file auxiliary_mod.py:
>
> class ClassA:
>
>  def fun(self):
>
>    import main_mod
>
>    print 'this is ClassA.fun() and global_string is ' +
> main_mod.global_string
>
>    return
>
> In words, the problem is: I've a main module which defines a global
> variable and instantiates a class defined in a second module, and a
> method of that class needs to access the global variable defined in the
> main module.
>
> When I run main_mod.py the method is executed twice:
>
> this is ClassA.fun() and global_string is abc
> this is ClassA.fun() and global_string is abc
>
> How can I avoid this problem even in this simple example? If I move the
> import main_mod statement to the outside of the definion of ClassA I
> get an exception:
>
> Traceback (most recent call last):
>  File "./main_mod.py", line 4, in ?
>    import auxiliary_mod
>  File "/manel/ewt/test/auxiliary_mod.py", line 4, in ?
>    import main_mod
>  File "/manel/ewt/test/main_mod.py", line 13, in ?
>    main()
>  File "/manel/ewt/test/main_mod.py", line 9, in main
>    instance = auxiliary_mod.ClassA()
> AttributeError: 'module' object has no attribute 'ClassA'
>
>
> As far as I can tell I'm following the technique suggested by Guido
> himself to handle mutual imports:
>
> "Guido van Rossum recommends avoiding all uses of from <module> import
> ..., and placing all code inside functions. Initializations of global
> variables and class variables should use constants or built-in
> functions only. This means everything from an imported module is
> referenced as <module>.<name>."
>
> [http://www.python.org/doc/faq/programming.html]
>
> How can I get this simple example to work?
>
> Thank you for any help in advance,
>
> Mack
> 




More information about the Python-list mailing list