ImportError: attempted relative import with no known parent package

Module imports sometimes can cause too much frustration if you are a Python beginner. This tutorial will learn how imports work and the solution for ImportError: attempted relative import with no known parent package.

Before getting into the solution, let’s first understand few basic terminologies in Python.

Python Module: A module is a file in Python containing definitions and statements. A module can contain executable statements as well as function definitions. In simple terms, think as a single .py file with some functionality.

Python Package: A Python package consists of one or more modules, and it contains one file named __init__.py that tells Python that this directory is a package. The init file may be empty, or it may include code to be executed upon package initialization.

imports: Imports in Python are essential for structuring your code effectively, and by using the import keyword, you can import any module and reuse it effectively. There are two types of import, Relative and Absolute, which will look in-depth.

Let’s consider a simple example. 

└── myproject
    ├── firstpackage
    │   ├── a.py
    └── secondpackage
        ├── b.py
        ├── c.py
        └── subpackage
            └── d.py

The above project has two packages named firstpackage and secondpackage. Each of these contains some modules, and the secondpackage also has a subpackage that includes its own module. Typically the project structure goes something like this, and it may grow pretty complex.

How does module import work in Python?

Now, let’s say if you import module b in one of your files using the import statement as shown below.

import b

Python will perform the following operations to import the module:

  • Locate, load, and initialize (if required) the requested module
  • Define necessary names in the local namespace and corresponding scope

Now Python interpreter is going to follow the following steps in an attempt to resolve module b .

Step 1: sys.modules lookup

Python will try to look at the module first in the sys.modules, which is a dictionary that has a mapping of key-value pairs of modules. If it finds, then the module is resolved and loaded.

Step 2: Python Standard Library lookup

Python Standard Library contains built-in modules (written in C) that provide access to system functionality such as file I/O that would otherwise be inaccessible to Python programmers. Modules are written in Python that provides standardized solutions for many problems that occur in everyday programming. Some of these modules are explicitly designed to encourage and enhance the portability of Python programs by abstracting away platform-specifics into platform-neutral APIs.

If the name is not found in the sys.modules, it will search in the standard library. If it cannot find over there, then it goes to the next step.

Step 3: sys.path lookup

Python will look into the sys.path as the last step to resolve the module. This is where things can go wrong, and you will get ModuleNotFoundError: No module named ‘b’

Absolute vs. Relative imports

In absolute imports, you need to specify the explicit path from the project’s root directory.

Example – If we have to import module b then we can use the following way to import

import secondpackage.b

Other ways of importing modules in Python

# importing modules a.py
import secondpackage.subpackage.d
import secondpackage.c

In case of relative imports, we need to specify the module’s path relative to the current module’s location.

Example –

# in module a.py
from ..secondpackage import b
from ..secondpackage.b import another_function
# in module b
from . import c
from .c import my_function

How to fix ImportError: attempted relative import with no known parent package?

Option 1 – Use absolute imports

For instance, the directory structure may be as follows

.
├── project
│   ├── package
│   │   ├── __init__.py
│   │   ├── module.py
│   │   └── standalone.py
│   └── setup.py

where setup.py is

from setuptools import setup, find_packages
setup(
    name = 'your_package_name',
    packages = find_packages(),
)

Option 2 – Get rid of from keyword

Remove the from keyword and use the standard way of import as shown below.

import secondpackage.c


Option 3 – Import inside package init file

Put this inside your package’s __init__.py file:

# For relative imports to work in Python 3.6
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))

Assuming your package is like this:

├── project
│   ├── package
│   │   ├── __init__.py
│   │   ├── module1.py
│   │   └── module2.py
│   └── setup.py

Now use regular imports in you package, like:

# in module2.py
from module1 import class1
Leave a Reply

Your email address will not be published. Required fields are marked *

Sign Up for Our Newsletters

Subscribe to get notified of the latest articles. We will never spam you. Be a part of our ever-growing community.

You May Also Like