To get a simple idea Lets look at the directory tree again
lib
├── c.py
├── dir1
│ ├── a.py
│ └── __init__.py
├── dir2
│ ├── b.py
│ └── __init__.py
└── __init__.py
Important things
- In this tree, the top most
__init__.py file is in the root directory.
- All other subfolders with python scripts are included
__init__.py
OK, Here comes the point. When you are trying to do relative import with .. it tries to import from lib.dir1.a, But there is no __init__.py at the same level with lib folder. That's why you get ImportError: attempted relative import beyond top-level package error. Because of python package importer doesn't identify lib folder as the top level package.
When you are trying to relative import with . , you checks dir2.dir1.a , which doesn't exit. Sow it will give you ModuleNotFoundError: No module named 'dir2.dir1' error
OK lets check whether it's true or not. lets add new folder dir3 within dir1 and d.py,e.py and __init__.py inside it
Here is the NEW directory tree
lib
├── c.py
├── dir1
│ ├── a.py
│ ├── dir3
│ │ ├── d.py
│ │ ├── e.py
│ │ └── __init__.py
│ └── __init__.py
├── dir2
│ ├── b.py
│ └── __init__.py
└── __init__.py
And here are the NEW file contents
a.py
def a_foo(a, b):
return a + b
b.py
from dir1.a import a_foo
def b_bar():
return a_foo(1,2)
e.py
def e_foo(a, b):
return a + b
d.py
from ..a import a_foo
from .e import e_foo
def d_bar():
return a_foo(1,2)
def d_foo():
return e_foo(1,2)
.. , Which tries to import from dir1.a, which exists and also which is accessible.
. , Which tries to import from dir3.e, which exists and also which is accessible.
c.py
from dir2.b import b_bar
from dir1.dir3.d import d_bar,d_foo
print("b_bar:", b_bar())
print("d_bar:", d_bar())
print("d_foo:", d_foo())
Now lets run c.py. The result is
b_bar: 3
d_bar: 3
d_foo: 3
Which indicates our relative import has been successful inside d.py.
OK then. I think this will solve your problem. We can use relative import in files which are in depth from the root-package. But when they are too close (within one or two levels), it's impossible.
Actually we can use . to import from python scripts in same level but not when the script is in the top most directory.