python circular dependency issue: unexpected error - python

I have some python files in a directory called 'circular_dependency':
import_file_1.py:
from circular_dependency.import_file_2 import *
def add_one(x):
return x+1
import_file_2.py:
from circular_dependency.import_file_1 import *
def add_two(x):
return add_one(add_one(x))
and finally main.py
from circular_dependency.import_file_1 import *
from circular_dependency.import_file_2 import *
x = 17
print(add_two(x))
running main.py results in the following error:
/Users/fabianwerner/anaconda3/envs/academy/bin/python /Users/fabianwerner/BI-X/academy/exercises/01_exMON_python/circular_dependency/main.py
Traceback (most recent call last):
File "/Users/fabianwerner/BI-X/academy/exercises/01_exMON_python/circular_dependency/main.py", line 5, in <module>
print(add_two(x))
File "/Users/fabianwerner/BI-X/academy/exercises/01_exMON_python/circular_dependency/import_file_2.py", line 4, in add_two
return add_one(add_one(x))
NameError: name 'add_one' is not defined
Process finished with exit code 1
As far as I have understood, python does not really cope well with circular (well, actually those are non-harmful) "circular" dependencies. So I would have expected an error where python complains about the fact that I have created a circular dependency.
--> Questions:
Why does python not complain about the circular dependency?
What does the error below mean? Why can't the function add_two in import_file_2.py find the function add_one from import_file_1.py althoug I have imported that function?
Thanks for clearing this up :-)

The order of the imports in main.py matters in this case.
Starting from main.py, you first import import_file_1. This causes contents of import_file_1 to be loaded into the namespace. Now as part of the first line of import_file_1.py, you import import_file_2, which adds add_two() to the namespace.
Note that by now, add_one() is still undefined. When control goes back into import_file_1, add_one() finally gets added to the namespace. However, logically, this happens after the definition of add_two() which raises the error.
Switching the import lines in main.py to the following fixes the issue:
from circular_dependency.import_file_2 import *
from circular_dependency.import_file_1 import *

1 - No idea
2 - What happens is:
Python stores the imported modules in it's cache, namely sys.modules. When a lookup / import happens, it first looks at the cache and uses it if the module is already imported. So, basically you can do import mymodule a hundred times and it's only imported the first time, rest will just be dictionary lookups.
In a circular dependency scenario:
file 1 imported
file 2 immediately imported due to import in file 1
file 1 immediately imported in file 2
file 1 is already in sys.modules so no need to import, continue to file 2
There you have an empty shell of file 1 in sys.modules. Referencing a function in file 1 will end up in name error.
You could do this instead:
file 2
def add_two():
from file1 import add_one
...

Related

Python ImportError: cannot import name '..' from partially initialized module '..' (most likely due to a circular import)

I've read the other threads on this but they haven't really helped me.
I have to 2 .py files, both located under ets.routes, called agreements.py and approvals.py.
The file agreements.py imports several methods from approvals:
from ets.routes.approvals import getPendingApprovals, getIsApprover
It itself also exposes a utility method which should be available to approvals called authorize_agreement.
Now in approvals.py if I do
from ets.routes.agreements import authorize_agreement
I get the error
ImportError: cannot import name 'getPendingApprovals' from partially initialized module 'ets.routes.approvals' (most likely due to a circular import)
(C:\gitForVS\app\api\ets\routes\approvals.py)
I can't move authorize_agreement to some external file like utils.py, it really should be in agreements.py because it uses a lot of DB and associated Agreement-level code which is available there. It's just that this function should be imported by its sibling, while it itself imports some of the sibling's functions. Why is that such an issue? Are you required to have 1-way imports (e.g. from approvals -> agreements only) in Python?
The reason you're getting an error is because agreements.py can't import functions from approvals.py while approvals.py is simultaneously trying to import functions from agreements.py (hence the circular import error). One of your modules needs to define the functions the other wants before importing the functions it wants from the other.
For example:
File A:
from fileb import sum2
def sum(a, b):
return a + b
File B:
def sum2(a, b):
return a + b + a
from filea import sum # This works

Python: Circular Import error, eventhough no "from ... import ..." used

I am struggeling with resolving a circular import issue. My setup is as follows:
Module a.py:
import b
class A():
pass
Module b.py:
import a
class Bar(a.A):
pass
Notice the circular import in module b: is needs to access class A from module a, because B inherits from A.
Finally, the main module, main.py:
import a
# ...
When I run main.py, I get this error:
$ python3 main.py
Traceback (most recent call last):
File "/home/.../main.py", line 1, in <module>
import a
File "/home/.../a.py", line 1, in <module>
import b
File "/home/.../b.py", line 3, in <module>
class Bar(a.A):
AttributeError: partially initialized module 'a' has no attribute 'A' (most likely due to a circular import)
I thought, one way of resolving circular imports was to not use the from ... import ... statement, which I didn't do as you can see. But why am I still getting that error then?
EDIT: My current code structure requires that A and B are separate modules. Nevertheless, in this video, he is using a similar structure as mine, and he has no problems...
The ideal answer in such cases is usually to
combine the files or their contents (do you actually need more files?)
create a 3rd file and put shared contents into it (avoids breaking existing imports as you can simply import whatever you need into the existing libraries from the shared one)
create a 3rd file which imports both (cleaner with 3rd party libraries, but may break existing logic)
import a
import b
class Bar(a.A):
pass

Calling of Nested Modules in Python

I have been recently working on a project with 150+ files and I am faced with a big hurdle in the switching modules.
I have a feature which allows switching of modules. It works in the following way (I am giving a simplified explanation):
Suppose there are 4 files as first.py, second.py, third.py, fourth.py and each of the following file has a module same as its filename which calls its previous function as below.
Content of first.py
from second import *
def first():
second()
Content of second.py
from third import *
def second():
third()
Content of third.py:
from fourth import *
def third():
q = raw_input('Use (f)ourth or go (b)ack?')
if q == 'f':
fourth() # proceed to fourth
elif q == 'b':
second() # back to second module
# this is how the switching of modules work
Content of fourth.py:
def fourth():
<stuff1>
Now when first() is called, the interpreter asks for f or b. If f, then the <stuff1> is executed, but when b is the input, it gives a NameError something like this.
Traceback (most recent call last):
File "first.py", line 4, in <module>
first()
File "first.py", line 3, in first
second()
File "test/second.py", line 3, in second
third()
File "test/third.py", line 7, in third
second()
NameError: global name 'second' is not defined
And this is basically how the switching back of modules is failing. I have tried importing second.py in third file by adding from second import second which did not help but instead put out an ImportError as ImportError: cannot import name second. Declaring function names as global variables too did not help.
Is there a any way how i can achieve this. Or there is a more efficient way to solve the switching problem.
Edit:
I understand that a circular dependency is being created, but is there any other way to getting the 4 modules up and running without creating this circular dependency.
It seems to me to be a circular import.
The problem is between second.py and third.py. You invoke third in second.py and then second in third.py.
You can read this article to find out what circular imports are and how to prevent them.
P.S. I would suggest not using this syntax for importing stuff from other modules.
from ... import *
This can produce name conflicts and you don't know what is inside this module.
Better option is to import the only things you need or to refer to a specific functions of a module.

Cyclic import in Python makes impossible to call function from the upper module

Here is my code below.
main.py:
import moduleA
print('It works!')
moduleA.py:
import moduleB
def functionA():
return 0
moduleB.py:
import moduleA
globalVariableFromModuleB = moduleA.functionA()
If I run it, I get the error message:
$ python main.py
Traceback (most recent call last):
File "main.py", line 3, in <module>
import moduleA
File "/home/asa/bugs/moduleA.py", line 3, in <module>
import moduleB
File "/home/asa/bugs/moduleB.py", line 8, in <module>
globalVariableFromModuleB_1 = functionB()
File "/home/asa/bugs/moduleB.py", line 6, in functionB
return moduleA.functionA()
Q1: In my case moduleB explicitly imports moduleA, thus I expect it to work, but it does not. Is this because Python cashes imports and does not do it twice? But why it cannot then take the already cashed moduleA.functionA() from the memory instead of failing? I suppose the current behavior is a bug therefore.
Q2: If I remove the line "globalVariableFromModuleB = moduleA.functionA()" and leave only the cyclic import "import moduleA" then I have no failure. So, cyclic dependencies are not forbidden in Python. For what are they allowed if they don't work correclty as it shows my example?
Q3: If I change "import moduleA" to "from moduleA import functionA" the main program does not work either failing with another message "ImportError: cannot import name functionA".
Also I would like to post here a workaround for the people who don't like to redesign the application, like in my case.
Workaround (found it just experimentally). To add "import moduleB" before the "import moduleA" in the main.py, that is:
# main.py
import moduleB
import moduleA
print('It works!')
But I had to leave a long comment right at this import in the code, because main.py does not use directly any API from moduleB, so it is looking ugly.
Could one suggest some better wa how to resolve such case and answer 3 questions above, please?
cyclic import in python are a very nasty "Gotcha"; this article explains all the ins an outs nicely - please consider carefully reading it.
To solve the problem you simply have to brake the cycle - in your case, you could drop the import ModuleA in moduleB, since it's not needed (you already import A in main)
To really understand what's going on, consider the following:
the you do import , python will load the code for
and execute it line by line and adds the to sys.modules so
that it knows it was already imported
if the imported contains another import statement, python will load and start executing that code, and then add the module name to sys.module
in your case sys.modules contains both moduleA and moduleB, but because the execution of module A was "interrupted" by the import moduleB statement the function definition never got executed, but the module dot added to sys.modules => AttributeError: 'module' object has no attribute 'functionA'
Hope this helps.
For instance, I would post here more complicated case (when each module calls a function from the other module in a global context) that works without significant redesign of the program:
main.py
import moduleA
print('Value=%s' % moduleA.functionA())
moduleA.py
globalVariableFromModuleA = 'globalA'
def functionA():
return globalVariableFromModuleA + '_functionA'
import moduleB
globalVariableFromModuleA = moduleB.functionB()
moduleB.py
globalVariableFromModuleB = 'globalB'
def functionB():
return 'functionB'
import moduleA
globalVariableFromModuleB = moduleA.functionA()
Result:
$ python main.py
Value=functionB_functionA
The value does not contain 'globalA' that shows that it works, because globalVariableFromModuleA from moduleA.py is correctly evaluated by moduleB.functionB().
And the next example shows that Python prevents endless recursion not only for importing of modules, but for function invocations as well.
If we modify moduleB.py the following way:
moduleB.py
globalVariableFromModuleB = 'globalB'
def functionB():
return globalVariableFromModuleB + '_functionB'
import moduleA
globalVariableFromModuleB = moduleA.functionA()
Result:
$ python main.py
Value=globalA_functionA_functionB_functionA
(at the second entering to functionA() it decided to not evaluate globalVariableFromModuleA more, but to take an initial value 'globalA')

Python NameError when importing functions from other files [duplicate]

I'm getting this error
Traceback (most recent call last):
File "/Users/alex/dev/runswift/utils/sim2014/simulator.py", line 3, in <module>
from world import World
File "/Users/alex/dev/runswift/utils/sim2014/world.py", line 2, in <module>
from entities.field import Field
File "/Users/alex/dev/runswift/utils/sim2014/entities/field.py", line 2, in <module>
from entities.goal import Goal
File "/Users/alex/dev/runswift/utils/sim2014/entities/goal.py", line 2, in <module>
from entities.post import Post
File "/Users/alex/dev/runswift/utils/sim2014/entities/post.py", line 4, in <module>
from physics import PostBody
File "/Users/alex/dev/runswift/utils/sim2014/physics.py", line 21, in <module>
from entities.post import Post
ImportError: cannot import name Post
and you can see that I use the same import statement further up and it works. Is there some unwritten rule about circular importing? How do I use the same class further down the call stack?
See also What happens when using mutual or circular (cyclic) imports in Python? for a general overview of what is allowed and what causes a problem WRT circular imports. See What can I do about "ImportError: Cannot import name X" or "AttributeError: ... (most likely due to a circular import)"? for techniques for resolving and avoiding circular dependencies.
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.
When you import a module (or a member of it) for the first time, the code inside the module is executed sequentially like any other code; e.g., it is not treated any differently that the body of a function. An import is just a command like any other (assignment, a function call, def, class). Assuming your imports occur at the top of the script, then here's what's happening:
When you try to import World from world, the world script gets executed.
The world script imports Field, which causes the entities.field script to get executed.
This process continues until you reach the entities.post script because you tried to import Post
The entities.post script causes physics module to be executed because it tries to import PostBody
Finally, physics tries to import Post from entities.post
I'm not sure whether the entities.post module exists in memory yet, but it really doesn't matter. Either the module is not in memory, or the module doesn't yet have a Post member because it hasn't finished executing to define Post
Either way, an error occurs because Post is not there to be imported
So no, it's not "working further up in the call stack". This is a stack trace of where the error occurred, which means it errored out trying to import Post in that class. You shouldn't use circular imports. At best, it has negligible benefit (typically, no benefit), and it causes problems like this. It burdens any developer maintaining it, forcing them to walk on egg shells to avoid breaking it. Refactor your module organization.
To understand circular dependencies, you need to remember that Python is essentially a scripting language. Execution of statements outside methods occurs at compile time. Import statements are executed just like method calls, and to understand them you should think about them like method calls.
When you do an import, what happens depends on whether the file you are importing already exists in the module table. If it does, Python uses whatever is currently in the symbol table. If not, Python begins reading the module file, compiling/executing/importing whatever it finds there. Symbols referenced at compile time are found or not, depending on whether they have been seen, or are yet to be seen by the compiler.
Imagine you have two source files:
File X.py
def X1:
return "x1"
from Y import Y2
def X2:
return "x2"
File Y.py
def Y1:
return "y1"
from X import X1
def Y2:
return "y2"
Now suppose you compile file X.py. The compiler begins by defining the method X1, and then hits the import statement in X.py. This causes the compiler to pause compilation of X.py and begin compiling Y.py. Shortly thereafter the compiler hits the import statement in Y.py. Since X.py is already in the module table, Python uses the existing incomplete X.py symbol table to satisfy any references requested. Any symbols appearing before the import statement in X.py are now in the symbol table, but any symbols after are not. Since X1 now appears before the import statement, it is successfully imported. Python then resumes compiling Y.py. In doing so it defines Y2 and finishes compiling Y.py. It then resumes compilation of X.py, and finds Y2 in the Y.py symbol table. Compilation eventually completes w/o error.
Something very different happens if you attempt to compile Y.py from the command line. While compiling Y.py, the compiler hits the import statement before it defines Y2. Then it starts compiling X.py. Soon it hits the import statement in X.py that requires Y2. But Y2 is undefined, so the compile fails.
Please note that if you modify X.py to import Y1, the compile will always succeed, no matter which file you compile. However if you modify file Y.py to import symbol X2, neither file will compile.
Any time when module X, or any module imported by X might import the current module, do NOT use:
from X import Y
Any time you think there may be a circular import you should also avoid compile time references to variables in other modules. Consider the innocent looking code:
import X
z = X.Y
Suppose module X imports this module before this module imports X. Further suppose Y is defined in X after the import statement. Then Y will not be defined when this module is imported, and you will get a compile error. If this module imports Y first, you can get away with it. But when one of your co-workers innocently changes the order of definitions in a third module, the code will break.
In some cases you can resolve circular dependencies by moving an import statement down below symbol definitions needed by other modules. In the examples above, definitions before the import statement never fail. Definitions after the import statement sometimes fail, depending on the order of compilation. You can even put import statements at the end of a file, so long as none of the imported symbols are needed at compile time.
Note that moving import statements down in a module obscures what you are doing. Compensate for this with a comment at the top of your module something like the following:
#import X (actual import moved down to avoid circular dependency)
In general this is a bad practice, but sometimes it is difficult to avoid.
For those of you who, like me, come to this issue from Django, you should know that the docs provide a solution:
https://docs.djangoproject.com/en/1.10/ref/models/fields/#foreignkey
"...To refer to models defined in another application, you can explicitly specify a model with the full application label. For example, if the Manufacturer model above is defined in another application called production, you’d need to use:
class Car(models.Model):
manufacturer = models.ForeignKey(
'production.Manufacturer',
on_delete=models.CASCADE,
)
This sort of reference can be useful when resolving circular import dependencies between two applications...."
I was able to import the module within the function (only) that would require the objects from this module:
def my_func():
import Foo
foo_instance = Foo()
If you run into this issue in a fairly complex app it can be cumbersome to refactor all your imports. PyCharm offers a quickfix for this that will automatically change all usage of the imported symbols as well.
I was using the following:
from module import Foo
foo_instance = Foo()
but to get rid of circular reference I did the following and it worked:
import module.foo
foo_instance = foo.Foo()
According to this answer we can import another module's object in the block( like function/ method and etc), without circular import error occurring, for example for import Simple object of another.py module, you can use this:
def get_simple_obj():
from another import Simple
return Simple
class Example(get_simple_obj()):
pass
class NotCircularImportError:
pass
In this situation, another.py module can easily import NotCircularImportError, without any problem.
just check your file name see if it is not the same as library you are importing.
Eg - sympy.py
import sympy as sym

Categories