Preface
In this article, I will analyze the cause of importerror: attached relative import with no known parent package
exception. When you are running a python script. This exception may occur when a package is referenced in a relative reference mode (similar to Import.. module
)
Let’s take a look at an example of this exception
Questions
Suppose you have the following directory structure:
project
├── config.py
└── demos
├── __init__.py
└── demo.py
config.py
contains some variables that should be used in demo.py
project/config.py
count = 5
project/demos/demo.py
from .. import config
print("The value of config.count is {0}".format(config.count))
When we try to run demo. Py
, we encounter the following errors:
E:\project> python demos/demo.py
Traceback (most recent call last):
File "demos/demo.py", line 1, in <module>
from .. import config
ImportError: attempted relative import with no known parent package
The Python interpreter threw an exception without a parent package. Why
Let’s see how the Python interpreter parses the relevant modules. From PEP 328, we find an introduction to the relative imports
:
Relative imports use a module’s __name__ attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to __main__ ) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
Relative imports determine the module's location in the package hierarchy by using the module's __name__ attribute. If the module's name does not contain any package information (for example, it is set to __main__), then the relative reference assumes that this module is the top-level module, regardless of the module's actual location on the filesystem.
In other words, the algorithm for solving the module is based on the value of the __name__
sum __package__
variable. Most of the time, these variables do not contain any package information—for example, when __name__
= __main__
and __package__
= None
, the python interpreter does not know which package the module belongs to. In this case, relative references will consider this module to be the top-level module, regardless of the actual location of the module on the file system.
To demonstrate this principle, let’s update the code:
project/config.py
print('__file__={0:<35} | __name__={1:<20} | __package__={2:<20}'.format(__file__,__name__,str(__package__)))
count = 5
project/package/demo.py
print('__file__={0:<35} | __name__={1:<20} | __package__={2:<20}'.format(__file__,__name__,str(__package__)))
from .. import config
print("The value of config.count is {0}".format(config.count))
Try running it again and you will get the following output:
E:\project> python demos/demo.py
__file__=demos/demo.py | __name__=__main__ | __package__=None
Traceback (most recent call last):
File "demos/demo.py", line 3, in <module>
from .. import config
ImportError: attempted relative import with no known parent package
As we can see, the Python interpreter does not have any information about the package to which the module belongs ( 0)__ name__
=__ main__
and __ package__
= none
), so it throws an exception that the parent package cannot be found
Solution 1
we create a new empty in it__ init__. Py
file to convert the project directory into a package
we create a file main. Py
in the parent directory of the project directory
toplevel
├── main.py
└── project
├── __init__.py
├── config.py
└── demos
├── __init__.py
└── demo.py
toplevel/main.py
print('__file__={0:<35} | __name__={1:<20} | __package__={2:<20}'.format(__file__,__name__,str(__package__)))
import project.demos.demo
Execute the new example, and the output is as follows:
E:\toplevel>python main.py
__file__=main.py | __name__=__main__ | __package__=None
__file__=E:\toplevel\project\demos\demo.py | __name__=project.demos.demo | __package__=project.demos
__file__=E:\toplevel\project\config.py | __name__=project.config | __package__=project
The value of config.count is 5
Importing project.demos.demo
in main. Py
will set the package information of relative reference ( main. Py
)__ name__ and __ package__
variable). Now, the Python interpreter can successfully resolve the relative references in project/demos/demo. Py
Solution 2
we create a new empty project in the
to convert the Project
folder__ init__. Py Project
directory into a package
in the top level
directory, use the - M
parameter to call the Python interpreter to execute project.demos.demo
[1]
toplevel
└── project
├── __init__.py
├── config.py
└── demos
├── __init__.py
└── demo.py
Again:
E:\toplevel>python -m project.demos.demo
__file__=E:\toplevel\project\demos\demo.py | __name__=__main__ | __package__=project.demos
__file__=E:\toplevel\project\config.py | __name__=project.config | __package__=project
The value of config.count is 5
Running this command will automatically set the package information ( 0__ package__
variable). Now, the Python interpreter can successfully resolve the relative references in project/demos/demo. Py
(even think that project/demos/demo__ name __
=__ main__
).
Note that when using the - M
parameter, the executable file specified later has no . Py
suffix
Note 2:
Another error that may be reported in actual use is the wrong path to execute the code
E:\toplevel>python -m project.demos.demo
Be sure to execute this command in the directory above the project