Why Do Circular Imports Seemingly Work Further Up in the Call Stack But Then Raise an Importerror Further Down

Why do circular imports seemingly work further up in the call stack but then raise an ImportError further down?

I think the answer by jpmc26, while by no means wrong, comes down too heavily on circular imports. They can work just fine, if you set them up correctly.

The easiest way to do so is to use import my_module syntax, rather than from my_module import some_object. The former will almost always work, even if my_module included imports us back. The latter only works if my_object is already defined in my_module, which in a circular import may not be the case.

To be specific to your case: Try changing entities/post.py to do import physics and then refer to physics.PostBody rather than just PostBody directly. Similarly, change physics.py to do import entities.post and then use entities.post.Post rather than just Post.

What happens when using mutual or circular (cyclic) imports in Python?

There was a really good discussion on this over at comp.lang.python last year. It answers your question pretty thoroughly.

Imports are pretty straightforward really. Just remember the following:

'import' and 'from xxx import yyy' are executable statements. They execute
when the running program reaches that line.

If a module is not in sys.modules, then an import creates the new module
entry in sys.modules and then executes the code in the module. It does not
return control to the calling module until the execution has completed.

If a module does exist in sys.modules then an import simply returns that
module whether or not it has completed executing. That is the reason why
cyclic imports may return modules which appear to be partly empty.

Finally, the executing script runs in a module named __main__, importing
the script under its own name will create a new module unrelated to
__main__.

Take that lot together and you shouldn't get any surprises when importing
modules.

Problem with inherits and circular imports

Something like this:

class A:
def __new__(cls):
from Bmodule import B
return super().__new__(B)

class B(A):
def __init__(self):
print("Class B was built")

print(A())

Python Resolving Circular Imports without merging files

Instead of setting compatible_enchantments on each of the ItemTypes, why not have a dictionary somewhere (probably in enchantments.py) that maps an EnchantmentType to the valid set of ItemTypes it can be applied to?

To me, it seems like the ItemType doesn't need to know about enchantments, but rather enchantments need to know if they can be applied to a particular ItemType.

Best Way to Resolve Circular Module Loading

The best way to deal with circular dependencies is to turn your circle into a triangle – that is, to make both classes that would depend on each other instead depend (at least in part) on some third Role.

Here's how that might look with the example you provided and a Shaveable role (Yaks should be Shaveable, right?):

Shaveable.rakumod

unit role Shaveable;

Yak.rakumod

use YakStore;
use Shaveable;

unit class Yak does Shaveable;

has YakStore $.yak-store is rw;

YakStore.rakumod

use Shaveable;
unit class YakStore;

has Shaveable $.yak is rw;

With that change, the tests in your example now pass.



Related Topics



Leave a reply



Submit