Cypridina Cypridina - 3 months ago 21
Python Question

Using class from another file in python package and conflicts in __init__()

I'm writing a python package (python 3.6) and have the following directory structure:

package/
| __init__.py
| fileA.py
| fileB.py
| tests/
| | __init__.py
| | test_classA.py
| | test_classB.py


Setup



My files have the following contents:

# package/fileA.py
from package import ClassB

def ClassA:
def __init__(self):
self.my_ClassB = ClassB()


-

# package/fileB.py
def ClassB:
def __init__(self):
self.foo = "bar"


-

# package/tests/test_classB.py
from package import ClassB

# <performs some unit tests here>


-

# package/tests/test_classA.py
from package import ClassA

# <performs some unit tests here>


-

# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB


Circular importing



When I ran
python test_classB.py
, I get the following traceback error showing that I have circular import statements, which are not allowed by python. Note - the package is not literally called
package
and I have edited the Traceback to match the toy example above.

Traceback (most recent call last):
File "package/tests/test_classB.py", line 2, in <module>
from package import ClassB
File "/anaconda/lib/python3.5/site-packages/package/__init__.py", line 2, in <module>
from .fileA import ClassA
File "/anaconda/lib/python3.5/site-packages/package/merparse.py", line 2, in <module>
from package import ClassB
ImportError: cannot import name 'ClassB'


Correcting the error



However, when I remove those two lines in my
package/__init__.py
file:

# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB


...and I change the import method for
package/fileA.py
:

# package/fileA.py
from package.fileB import ClassB

def ClassA:
def __init__(self):
self.my_ClassB = ClassB()


...
package/tests/test_classB.py
runs correctly.

My Question



My question is: How can I keep the one file: one class structure in my files and import with
from package import ClassA
instead of having to import with
from package.fileA import ClassA
?

In my package I would like to import classes from other files, but don't know how to get around circular importing.

Edit: Solution



Thanks to @mirandak and @martin-kalcok below for their help.

The only file that I had to edit was
fileA.py
to not refer to the package name in the import statement.

# package/fileA.py
from .fileB import ClassB

def ClassA:
def __init__(self):
self.my_ClassB = ClassB()


The
package/__init__.py
file still contains import statements in case I want to import the package from other scripts in the future that I don't couple with the package.

# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB

Answer

The problem is with package/fileA.py. It's both a part of package and calling the __init__.py file of package as it's imported - creating a circular dependency.

Can you change fileA.py to look like this?

# package/fileA.py
from .fileB import ClassB

def ClassA:
    def __init__(self):
        self.my_ClassB = ClassB()