0

When module A imports B, and B imports A, I get error: ImportError: cannot import name from partially initialized module (most likely due to a circular import).

However, if I merge contents of both modules into one, no error happens. Is there a reason why python does not treat circularly imported files as one big one?

I understand, that ambiguity arises: "Which to run first?", but that can be easily achieved by slightly adjusting syntax of imports and specifying the priority/order of import. Something like:

from foo import A priority 2
from foo import B priority 1

Please provide counter-arguments, if you see any.

4
  • I don't think this discussion is on-topic for this site. However, if it is, it's extremely unclear why priority 2 fixes the problem. Probably you have a real example in mind. It's very easy to create an actual circular import example, I would recommend providing such an example and then explaining why adding this priority statement resolves things. Commented Oct 27, 2022 at 17:44
  • It is really easy to provide (or imagine) a circular import. However, "priority" is not a real import keyword. I have posted this in order to (with your help) gain understanding of some cases that I might not have considered, before submitting a feature enhancement proposal to python group. If you must flag me, I will not blame you. However it would help the good if you did not. Commented Oct 27, 2022 at 17:53
  • I understand priority isn't critical to the problem, but this question nor any of its answers actually explore circular imports. You are solely investigating import statements, but you don't actually consider the consequences of importing from the two files. You don't import another module for no reason, you do so to import functions, and to import classes (and globals). This priority statement, or whatever keyword you choose, should address problems importing functions and classes that may or may not be dependent on one another. Commented Oct 27, 2022 at 18:55
  • Maybe you can resolve this issue using a keyword, I'm not sure. But if you limit this discussion solely to the import statements in a python module, you're ignoring the majority of the issues that could arise. Commented Oct 27, 2022 at 18:56

2 Answers 2

1

I think the main reason that answers your question lays in that Python is an interpreted language. Your script does not run, it is read by the interpreter line by line subsequently (if a different, specific, pattern is not explicitly coded), and the interpreter executes the code you ask for.

For many reasons, one of which is performance, the interpreter cannot (or, better, is not designed to) inspect your whole script to search for patterns. This is completely different from what happens in compiled languages (e.g. C/C++), where the compiler spends much time looking at your code, building up an idea of what you want to do overall, and then (and only then) generates a byte code optimized to do the job you asked for (the optimisation parameters are up to you).

Coming back to Python, imagine when script A is importing script B, and at a certain line of script B, script A (that is still being imported... Recall? The interpreter proceeds line by line) is requested to be imported. It's easy to understand that I cannot proceed with the importing of script A since it relies on B and B is not yet fully imported.

When asking why something has been designed that way, please, do not thing to the most banal example, but to the most complex (or weirdest) one.

Some technics like TYPE_CHECKING can be used to avoid circular error while declaring types from a partially imported module. That's fine, since it's a specific, narrow case, where you're explicitly stating that you're not going to use any object from module A in module B before the former has been completely imported, but you just need to declare in advance their type being.

Hope I've been clear, though I'm aware my answer is not rigorous. Suggestion from those who are more expert than me in programming theory are warmly adviced.

Sign up to request clarification or add additional context in comments.

Comments

0

Your example demonstrates the simplest case of circular imports. Solving the general case is vastly more complicated, possibly intractable.

Now consider import chains with multiple loops and loops on loops.

1 Comment

Thank you for participating in the discussion. But, I still don't see a problem. In the end it is just one looong file of codelines. All boils down to a good priority calculating algorithm, no?

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.