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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to