9

One way is to use import x, without using "from" keyword. So then you refer to things with their namespace everywhere.

Is there any other way? like doing something like in C++ ifnotdef __b__ def __b__ type of thing?

6
  • 2
    Don't have circular dependencies, create z by combining dependencies of x in y, and dependecies of y in x Commented Dec 13, 2012 at 20:13
  • This post is a duplicate: stackoverflow.com/questions/744373/… Commented Dec 13, 2012 at 20:14
  • 2
    @alinsoar It's not an exact duplicate -- that question asked what happens when you have circular imports; and this question asks for techniques to avoid them. Commented Dec 13, 2012 at 20:22
  • It is about 2 modules that import each other, i.e. circular. I did not watch if the solution. The problem is the same. Commented Dec 13, 2012 at 20:24
  • Are you trying to do from foo import bar, or from foo import *? Because if it's the latter, the answer is, don't do that. There are only a few special cases (outside of quick&dirty scripts or interactive sessions, where circular imports won't come up) where you want to do that, and I can't think of any case where from foo import * and mutual dependence both make sense. Commented Dec 13, 2012 at 20:26

3 Answers 3

10

Merge any pair of modules that depend on each other into a single module. Then introduce extra modules to get the old names back.

E.g.,

# a.py
from b import B

class A: whatever

# b.py
from a import A

class B: whatever

becomes

# common.py
class A: whatever
class B: whatever

# a.py
from common import A

# b.py
from common import B
Sign up to request clarification or add additional context in comments.

1 Comment

This forces one to start declaring everything in common.py rather than a.py and b.py. Not a good solution IMHO.
5

Circular imports are a "code smell," and often (but not always) indicate that some refactoring would be appropriate. E.g., if A.x uses B.y and B.y uses A.z, then you might consider moving A.z into its own module.

If you do think you need circular imports, then I'd generally recommend importing the module and referring to objects with fully qualified names (i.e, import A and use A.x rather than from A import x).

1 Comment

What if one is doing some explicit type checking? I am trying to do that right now so I can provide a very detailed error message, rather than some obfuscated traceback that my customers don't understand.
2

If you're trying to do from A import *, the answer is very simple: Don't do that. You're usually supposed to do import A and refer to the qualified names.

For quick&dirty scripts, and interactive sessions, that's a perfectly reasonable thing to do—but in such cases, you won't run into circular imports.

There are some cases where it makes sense to do import * in real code. For example, if you want to hide a module structure that's complex, or that you generate dynamically, or that changes frequently between versions, or if you're wrapping up someone else's package that's too deeply nested, import * may make sense from a "wrapper module" or a top-level package module. But in that case, nothing you import will be importing you.

In fact, I'm having a hard time imagining any case where import * is warranted and circular dependencies are even a possibility.

If you're doing from A import foo, there are ways around that (e.g., import A then foo = A.foo). But you probably don't want to do that. Again, consider whether you really need to bring foo into your namespace—qualified names are a feature, not a problem to be worked around.

If you're doing the from A import foo just for convenience in implementing your functions, because A is actually long_package_name.really_long_module_name and your code is unreadable because of all those calls to long_package_name.really_long_module_name.long_class_name.class_method_that_puts_me_over_80_characters, remember that you can always import long_package_name.really_long_module_name as P and then use P for you qualified calls.

(Also, remember that with any from done for implementation convenience, you probably want to make sure to specify a __all__ to make sure the imported names don't appear to be part of your namespace if someone does an import * on you from an interactive session.)

Also, as others have pointed out, most, but not all, cases of circular dependencies, are a symptom of bad design, and refactoring your modules in a sensible way will fix it. And in the rare cases where you really do need to bring the names into your namespace, and a circular set of modules is actually the best design, some artificial refactoring may still be a better choice than foo = A.foo.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.