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.