1

I have my module structure as following:

/parent
-- __init__.py
-- /child
---- __init__.py

I want to import child in parent and vice versa, I.E.:

/parent/init.py:

import child

/parent/child/init.py:

import parent

but when I do it I get the error No module named 'parent' in parent/child/__init__.py

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Tomergt45
  • 579
  • 1
  • 7
  • 19

3 Answers3

0

You are getting that error because of the circular dependency of modules in your code.

When python tries to initialize your parent module it sees the import child statement, which leads the interpreter to the child module, (Notice that parent module is not initialized yet) now in the child module import parent line is encountered, but since the parent module is not initialized yet, the interpreter will fail with the error that it cannot find the parent module.

Ideally, you should fix the circular imports to solve this problem, But it can be overcome moving the import to a later stage instead of adding it at the top of the file. (For example: you can add the import statement in a method where you will be actually using the child module.) but it is not recommended to do this.

Optimus
  • 697
  • 2
  • 8
  • 22
0

Add the parent path before importing it in child, this way parent module can be found

sys.path.append(os.path.abspath('..'))
Hicham Zouarhi
  • 1,030
  • 1
  • 18
  • 28
  • This solution only works if you are writing your code directly from `parent`, but what if there is another "grandparent" module which imports `parent`? then the appended path breaks (i.e. `abspath('..')` returns the path to "grandparent" instead of `parent`) – Tomergt45 Aug 17 '20 at 13:13
  • @Tomergt45 a grandparent module can directly import parent if you put a `__init__.py` file – Hicham Zouarhi Aug 17 '20 at 13:17
  • I added `print(os.path.abspath('..'))` in `child` and executed them one by one where each imports their child (grandparent imports parent, parent imports child), `child` printed `grandparent/parent`, `parent` printed `grandparent` and `grandparent` printed the path to it's parent directory – Tomergt45 Aug 17 '20 at 13:21
  • so the imports should work now, or is there something I don't understand ? – Hicham Zouarhi Aug 17 '20 at 13:22
  • 1
    Sorry if my explanation is bad, When I import `parent` in `grandparent`, it imports `child` in `parent`, in `child` it appends `abspath(..)` to look for its parent, but because the code runs from `grandparent` then `abspath(..)` returns the parent directory of `grandparent` and not `child`, which means `child` can't import `parent` – Tomergt45 Aug 17 '20 at 13:25
  • what if in child you do the import with `import grandparent.parent` ? I'm not sure if it's the best way to do it – Hicham Zouarhi Aug 17 '20 at 13:29
  • it's the same problem because `child` doesn't know where to find `grandparent` – Tomergt45 Aug 17 '20 at 13:30
0

Bad design alert

Circular imports problems can indicate bad design

Solution

Your imports can't be both on top level.

# /parent/child/init.py:

import parent  # <-- top level

# /parent/init.py:

import .child  # <-- also top level

Common pattern is to move one of the import to place, where it is used (but not on top level), eg:

# /parent/child/init.py:

def dupa():
    import parent  # <-- not top level
    parent.foo()

See also

Python circular importing?

D.Kallan
  • 157
  • 9
voy
  • 1,568
  • 2
  • 17
  • 28
  • 1
    Thank you for your comment, in reality, my parent module is `utils` and my child module is `tfutils` which indicates utils for `tensorflow`, I need some of the functions in `utils` inside `tfutils` so that's the reason for my circular imports – Tomergt45 Aug 17 '20 at 13:27