Addind imports to a class namespace

Dave Angel davea at ieee.org
Sat Jul 11 13:56:04 EDT 2009


Ryan K wrote:
> Thanks for your help Peter.
>
> I'm thinking that perhaps this isn't a circular import and that I
> don't understand importing. Here is a better explanation of my case (I
> am using Django):
>
> I have file x.py that declares classes A, B, C.
>
> There is also a file y.py that contains two methods T, U and the class
> that we are talking about above.
>
> x.py uses a dispatcher system to connect a signal to methods T and U
> in y.py so it does: from y import T, U.
>
> y.py needs to use classes A, B, C which is basically Menu and Link
> (and some other class) above so I am thinking that if in y.py I have
> from x import A, B, C that will cause a circular import?
>
> Is this not correct and if it isn't can you explain why? Does using
> from ... import X, Y, Z, i.e. explicit imports avoid this problem or
> does it exacerbate it?
>
> Thanks,
> Ryan
>
>   
You indeed have described a circular import.  In this case, a mutual 
dependency exists between x.py and y.py.  This can and nearly always 
should be avoided.  That's independent of the language involved, in any 
language, circular dependencies are a code smell

Now, in Python in particular, first question is whether either x.py or 
y.py is your main script module (the one where you do the if __name__ == 
"__main__"  and the answer is yes).  If so, you're in big trouble, and 
you really need to rework it.  I could elaborate if needed, but trust 
me, you don't want to do this, even if it means writing one more module 
containing a single import line and just two or three more, and letting 
that be your script.

If that's not the case, next question is whether either module refers to 
the other one at import time, or only from inside def and class 
definitions.  If you have any top-level code going on, other than 
imports, and this code actually uses a symbol from the other module, 
you're probably in trouble.  Not as bad as first case, but still worth 
avoiding.  Sometimes this can be kludged past, by reordering things a 
little bit, maybe by moving one of the imports further down in the file.

Now back to the code smell.  If the modules really depend on each other, 
you should consider factoring out those dependencies and move them to a 
third module that both import.  Figure out why the modules are broken up 
in the particular way they are, and how you can eliminate circular 
references by refactoring.  It's hard for me to come up with general 
principles, but perhaps an example or three will help.

If a callee needs configuration information stored in globals of the 
caller, then you probably need to add that config information as parameters.

If an object needs a reference to functions in another module, add them 
when constructing the object, not statically.

Or maybe even have the one module explicitly set global variables in the 
other module, so they're in one place, instead of being only in the 
namespace of the code initializing them.

That's the best I can do without something concrete to adjust.

DaveA



More information about the Python-list mailing list