- Attempted relative import with no known parent package
- 3 Answers 3
- 3 Best Solutions For “ImportError: attempted relative import with no known parent package” [2021 Updated]
- Why “ImportError: attempted relative import with no known parent package” is Raised?
- Avoid ImportError: attempted relative import with no known parent package
- 2 Ways to Check Whether the module belongs to a package
- Sample for “ImportError: attempted relative import with no known parent package”
- Review the __name__ and __package__ variables
- How to fix “ImportError: attempted relative import with no known parent package”
- Solution 1 : Change Directory Structure
- It works. Let’s see why?
- Solution 2 : Use the -m option
- It works. Let’s see why?
- Solution 3 : Workaround Without Changing Directory Structure
- It works. Let’s see why?
- Summary
- 4 thoughts on “ 3 Best Solutions For “ImportError: attempted relative import with no known parent package” [2021 Updated] ”
- ImportError: Attempted Relative Import With No Known Parent Package (Python)
- Table of Contents
- How to Solve ImportError: Attempted Relative Import With No Known Parent Package (ModuleNotFoundError: No module named ‘name’)
- Understand the Error ImportError: Attempted Relative Import With No Known Parent Package
Attempted relative import with no known parent package
This line is giving error
ImportError: attempted relative import with no known parent package
What is this error and how to resolve this error?
3 Answers 3
Apparently, box_utils.py isn’t part of a package. You still can import functions defined in this file, but only if the python script that tries to import these functions lives in the same directory as box_utils.py , see this answer.
Nota bene: In my case, I stumbled upon this error with an import statement with one period, like this: from .foo import foo . This syntax, however, tells Python that foo.py is part of a package, which wasn’t the case. The error disappeared when I removed the period.
If a different dictionary contains script.py , it can be accessed from the root. For instance:
If your program is structured.
. then a script in the epsilon directory can be called by:
from alpha.gamma.epsilon import script
Content of bar.py
If someone is getting the exactly same error for from .foo import func .
It’s because you’ve forgot to make it a package. So you just need to create __init__.py inside package directory.
Источник
3 Best Solutions For “ImportError: attempted relative import with no known parent package” [2021 Updated]
Relative imports in python can be frustrated from time to time. Therefore, from time to time, you may meet the mysterious and obscure exception “ImportError: attempted relative import with no known parent package” Let’s see what this exception means, why it is raised. Finally, we see how to get rid of the “ImportError: attempted relative import with no known parent package” exception
Why “ImportError: attempted relative import with no known parent package” is Raised?
As a rule of thumb – If you try to do relative import in a module that does not belong to a package, you will get the “ImportError: attempted relative import with no known parent package” exception.
Why? The reasons beyond this rule of thumb are related to how relative import works in python.
In PEP 328 (Imports: Multi-Line and Absolute/Relative) that add the support of relative imports, we can find how the python interpreter should resolve the relative modules.
Relative imports use a module’s __name__ attribute to determine that module’s position in the package hierarchy.
First, this statement implies that relative import is relative to the current package. What is the current package? The current package is the package the current module belongs to. However, you probably know that not all modules belong to a package. Therefore, the module where we do the relative import must belong to a package, or otherwise, the python interrupter will scream that you are doing something wrong.
Second, this statement describes how the python interrupter should find the current package when it searches for the imported module. When the Python interrupter tries to find out the current package, It obtains the package information by checking the value of the __name__ variable (the module’s name).
What should the interrupter do when the module’s name does not contain any package information?
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.
If __name__ variable does not have any package information, the python interpreter should treat the module as a top-level module (a module that does not belong to any package). In that case, the current package does not exist. Therefore, the python interpreter can not resolve the location of the imported module and you get “ImportError: attempted relative import with no known parent package“
This description shows one of the best example of a module that does not belong to a package : the __main__ module. The __main__ module, the script you invoked the python interrupter with, does not belong to any package. We use this example later to demonstrate how to get rid of “ImportError: attempted relative import with no known parent package” exception.
Avoid ImportError: attempted relative import with no known parent package
As we see, when you try to do relative import in a module that does not belong to a package, you will get the “ImportError: attempted relative import with no known parent package” exception. It is essential to know that the module where you do relative import belongs to a package; otherwise, you get this irritating exception.
2 Ways to Check Whether the module belongs to a package
One way to check if a module belongs to a package is to review the value of __name__ variable. If the __name__ variable contains a dot, the module belongs to a package.
Another way to check if a module belongs to a package is to review the value of __package__ variable. if the __package__ variable do not equal to None , the module belongs to a package.
Sample for “ImportError: attempted relative import with no known parent package”
The following sample demonstrates that the main module (The script you invoked the python interrupter with) does not belong to a package.
Suppose you have a project with the following simple directory structure:
Sample Directory Structure
You are trying access variables defined in the config.py in your program.py . It seems a straightforward task and you choose to use relative import:
root/config.py
root/package/program.py
However, when invoking program.py script, An exception is raised :
“ImportError: attempted relative import with no known parent package” Is Raised
Review the __name__ and __package__ variables
Let’s review the values of the __name__ and __package__ variables by adding some log messages at the top of the above modules:
root/config.py with logs
root/package/program.py with logs
Invoking program.py
As we can see in the above output, the value of the value of __package__ is None and the value of __name__ variable is __main__ .
Since, the value __package__ is None and the value of the variable __name__ does not contains any dot, we can know that module does not belong to any package. Therefore, the python interrupter raises the unclear exception.
How to fix “ImportError: attempted relative import with no known parent package”
Solution 1 : Change Directory Structure
In this solution, we need to change directory structure and create a new script
- First, create a new directory named new_root and move the root directory to new_root
- Create main.py in new_root directory
- Create a new empty __init__.py inside the root directory. This will signal to the python interrupter that this directory is a package.
The sample directory
Updating new_root/main.py
When we invoke the new script, we get the following output:
Invoking program.py
It works. Let’s see why?
Now, the module root.package.program belongs to root.package .
We can see it in the second line (The print from the top of new_root/root/package/program.py).
Now, when this module belong to a package, the python interpreter has all the information has all the information to resolve the relative import in root/package/program.py successfully.
Solution 2 : Use the -m option
In the first solution, we need to create a new script. In this solution, we use -m option without creating a new script.
Let’s change directory structure and use -m option
- First, create a new directory named new_root and move the root directory to new_root
- Create a new empty __init__.py inside the root directory. This will signal to the python interrupter that this directory is a package.
The sample directory
Now, we invoke python with -m option and provide the module root.package.program .
The python -m option allows modules to be located using the Python module namespace for execution as scripts. As the following output demonstrate, It will also set the package information:
Invoking program.py with -m option
It works. Let’s see why?
Now, the module root.package.program belongs to root.package .
We can see it in the first line (The print from the top of new_root/root/package/program.py).
Now, when this module belong to a package, the python interpreter has all the information has all the information to resolve the relative import in root/package/program.py successfully.
Note: Unlike PEP 328, the python interpreter do not rely on the value of __name__ to find the package information and uses the value of __package__.
Solution 3 : Workaround Without Changing Directory Structure
In previous solutions, we needed to change the directory structure. Sometimes, you want to avoid changing the directory structure. For example, the framework you use in your code (such as django, pytest, airflow, fastapi or flask) or the environment you work with (such as pycharm, vscode or jupyter notebook) depend on this directory structure. In those cases, you may consider the following workaround.
As we see in solution 2, the python interrupter relies on the __package__ variable to extract the package information. Therefore, when the __package__ is none, the python interrupter will cry that you are doing something wrong.
So, Let’s use this observation and enclose the relative import with the following if statement based on the value of the __package__ variable.
Invoking program.py with -m option
It works. Let’s see why?
If the __package__ is not None, we can safely use relative import. However, if __package__ is None, we can not use relative import anymore. Therefore we add the directory of the module to sys.path and import the required module. Since sys.path is a list of paths that specify where the python interrupter should search for imported modules, python interrupter will find the required module.
How to generate the directory?
First, replace the first dot in the relative import with os.dirname(__file__) and then replace each successive dot with “../”. Now append successive part between the dots.
from . import config | sys.path.append( os.dirname(__file__) ) import config |
from .. import config | sys.path.append( os.path.join( os.dirname(__file__), ‘..’ ) ) import config |
from … import config | sys.path.append( os.path.join( os.dirname(__file__), ‘..’ , ‘..’ )) import config |
from ..a.b.c import config | sys.path.append( os.path.join( os.dirname(__file__), ‘..’ , ‘a’ ,’b’ ,’c’ )) import config OR better (less chance for name clashing) sys.path.append( os.path.join( os.dirname(__file__), ‘..’ )) |
relative import : examples of adding path to sys.path
However, this method is very fragile. If a module with the required name (in our case, config) already exists in the sys path’s previous paths, the python interrupter will import it instead of our module. It can be a source of nasty and mysterious bugs.
So use this workaround with caution and only when necessary.
Summary
We see how the python interrupter resolve relative imports. Then, we see why the “ImportError: attempted relative import with no known parent package” exception is raised. Finally we see how to get rid of “ImportError: attempted relative import with no known parent package”
4 thoughts on “ 3 Best Solutions For “ImportError: attempted relative import with no known parent package” [2021 Updated] ”
This is it. This is by far the best article that concisely explain a python project structure. I cannot thank you enough!
I am glad that this tutorial helps you to understand how relative imports works in python.
Relative imports in python are not intuitive and can be frustrating :-*(
Источник
ImportError: Attempted Relative Import With No Known Parent Package (Python)
This is about the error ImportError: attempted relative import with not known parent package in Python.
- The meaning of the error ImportError: attempted relative import with not known parent package
- How to solve the error ImportError: attempted relative import with not known parent package
- Lots more
So if you want to understand this error in Python and how to solve it, then you’re in the right place.
Let’s get started!
Table of Contents
How to Solve ImportError: Attempted Relative Import With No Known Parent Package (ModuleNotFoundError: No module named ‘name’)
For example, you get the error when running a file inside a package as a script.
To get rid of the error ImportError: attempted relative import with no known parent package you have two ways to test package functions:
- Run a script with the -m switch.
- Use global import inside the package files that you plan to run as scripts.
To get rid of the former version of this error ModuleNotFoundError: No module named ‘name’, the path to the package folder must be in the PATH system variable. You can do this in different ways, for example:
- Move the package folder to a directory that is already in PATH.
- Add the folder where the package is located to PATH on your own through the console or system settings.
- Install the package to the system using the setuptools module.
- Add the address of the package folder to PATH using the sys and pathlib modules in those package files that you plan to run as a separate script.
Let’s dive right in:
Understand the Error ImportError: Attempted Relative Import With No Known Parent Package
One of the key advantages of the Python language is its infrastructure. You can find a ready-made module for almost any of your tasks.
The meme from xkcd below is a good illustration of this statement:
In this comic, one man says that flying is a straightforward task; you just need to type import antigravity. WARNING! Don’t try to import antigravity at home without securing fragile items.
It’s effortless to create your modules and packages for Python. However, this also has a downside. As packages evolved, some of the internal names in packages began to duplicate global ones.
For example, there is a package called graphics, but this is a fairly common word and it is inevitably used in other packages related to graphics.
Let’s say you created a supergraphics package with the following structure:
How can you determine when to call import graphics inside the unittests.py file, whether you mean a package from PyPI (Python Package Index) (let’s assume that you have installed it) or a local module inside your library?
One way is to always use an absolute import:
But in Python you can use the so-called relative import. Its capability and usage are specified in PEP328.
Relative imports are implemented as follows: You can use one dot . to import a package from the same level where you are. If you import graphics from unittest.py, you would write this:
If you need to import something from another folder, you would put a point to rise to a higher level.
For example, to import graphics from the shrink.py file, you would write this:
You can consider that the invisible word parent precedes each dot:
This makes the principle a little clearer, but writing this, of course, is not very convenient. In the end, you can use global imports.
Thanks to relative imports, you can add new folders to the package structure. This will not always require you to redo all imports.
For example, if you want to move all your current folders and files to a higher-level folder, this will not cause changes in the child files.
Relative imports are allowed only within a package. This is consistent with common sense and safety. Only the folder structure within the package can be guaranteed.
A package is an independent structural unit, and its components should not interact with relative paths with neighbouring packages.
It is very easy to create a Python package; you just need to create an __init__.py file in the root of the folder to import this folder as a package.
Let’s create a little module with the following folder structure and file contents:
You can now use your package from the Python terminal:
Now let’s add testing to the introduce.py file. It will look like this:
Now you can import the hello_to() function from it.
If you run the introduce.py file as a script, it will check on whether the value returned from the hello() function contains the name that you submitted to as an argument.
If you try to run this file as a script, you will get an ImportError: attempted relative import with no known parent package:
Another solution would be to not use relative imports.
Let’s change the introduce.py file as follows:
Now you can run this file as a script without the -m key:
A separate problem may be that Python does not know where the package is located.
Let’s move the package down one level inside the Project folder and try again to run introduce.py:
To get rid of this problem, you need to add the package’s folder path to PATH or place the package in a folder that is already in PATH. For example,
Before adding a module’s address to PATH or copying it to a folder that already exists in PATH, you must ensure that your package name is unique.
Otherwise, one of the packages will not work—either yours or the one already installed with the same name.
For your package to be globally available, Python has a special mechanism.
You can install your package using the utilities from the setuptools module.
Let’s create a setup.py file with the following content in the root folder of the package:
Next, start installing the package with the following command. By the way, you should always use a virtual environment; do not install any packages in the global interpreter.
For Python 3, there is a built-in venv utility. This is very useful if, for example, you have to use different versions of libraries in your different projects:
After launching, you will get a long installation log. If there were no errors, you could use the hi module globally.
If for some reason you do not want to install your module into the system, you can add the current directory to the path.
Make sure you do this before all imports from the module. Add a block that will modify PATH to the introduce.py file:
Now you can use global import in your introduce.py file even if the hi module is not installed in the system via setuptools.
Note that file.parents[1] is being used here because you need to move up one level for the hi package to be available.
In other words, you must go to the folder where the folder with the package is located. In the current case, this is Project:
If the tree structure were deeper, then the parents with higher indices would have to be used.
Источник