I am dealing with a problem with circular imports in Python. As a result of tackling this problem, I have had to become more knowledgeable about packages/imports in Python.
Some resources that I used include:
https://docs.python.org/3/tutorial/modules.html
https://chrisyeh96.github.io/2017/08/08/definitive-guide-python-imports.html
How to avoid circular imports in Python?
Circular (or cyclic) imports in Python
I know this topic has been discussed extensively, and I have done my best to become familiar with that discussion, but I have a minimum working example from our code base that I have yet to be able to resolve using the skills I learned from the sources that I cited above. I ask for any advice regarding this example.
The folder structure for the example is as follows:
Source/
Package/
__init__.py
A/
__init__.py
a.py
B/
__init__.py
b1.py
b2.py
C/
__init__.py
c1.py
c2.py
Every __init__.py
is empty. The contents of each file is as follows:
a.py
from Package.B.b1 import class_b1
b1.py
from Package.B.b2 import method_b2
class class_b1(object):
def __init__(self):
pass
b2.py
from Package.C.c1 import class_c1
def method_b2():
pass
c1.py
import Package.C.c2 as class_c2
class class_c1(object):
def __init__(self):
pass
c2.py
from Package.B.b1 import class_b1
class class_c2(object):
def __init__(self):
pass
The logic is as follows.
I export PYTHONPATH=/path/to/Source
to place Package
in the sys path.
I then go to Package/A
and execute python a.py
.
a.py loads a class from b1.py which loads a method from b2.py which loads a class from c1.py which loads a class from c2.py which loads a class from b1.py (namely the same class that a.py loaded). This results in an ImportError
Note that all of this is being done in an activated python 3.6.5 virtual env in Ubuntu 16.04.
Here is a trace:
(eye_tracking) gsandh16@count:~/Documents/PythonImportTesting/MWE_refactored/Source/Package/A$ python a.py
Traceback (most recent call last):
File "a.py", line 1, in <module>
from Package.B.b1 import class_b1
File "/home/gsandh16/Documents/PythonImportTesting/MWE_refactored/Source/Package/B/b1.py", line 1, in <module>
from Package.B.b2 import method_b2
File "/home/gsandh16/Documents/PythonImportTesting/MWE_refactored/Source/Package/B/b2.py", line 1, in <module>
from Package.C.c1 import class_c1
File "/home/gsandh16/Documents/PythonImportTesting/MWE_refactored/Source/Package/C/c1.py", line 1, in <module>
import Package.C.c2 as class_c2
File "/home/gsandh16/Documents/PythonImportTesting/MWE_refactored/Source/Package/C/c2.py", line 1, in <module>
from Package.B.b1 import class_b1
ImportError: cannot import name 'class_b1'
I would like to resolve the issue without refactoring code or sticking imports in method calls (i.e. when they actually use the imported package). I have tried various absolute imports, relative imports, appending to sys.path by getting the location of the current file. My gut tells me it has to do with what the sys.path is as the program goes.
Thank you for any help regarding this issue.