Home >Backend Development >Python Tutorial >Why Do Relative Imports in Python 3 Fail, and How Can I Fix Them?

Why Do Relative Imports in Python 3 Fail, and How Can I Fix Them?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-12-27 14:49:17978browse

Why Do Relative Imports in Python 3 Fail, and How Can I Fix Them?

Relative Imports in Python 3: The Mysterious Errors

In Python 3, relative imports are a convenient way to import modules from within the same directory. However, an unexpected error often arises:

Error Messages:

  • ImportError: attempted relative import with no known parent package
  • ModuleNotFoundError: No module named 'mymodule'
  • SystemError: Parent module '' not loaded, cannot perform relative import

The Root Cause:

To understand these errors, we must delve into Python's module importing mechanism. Relative imports require that the importing module is contained within a package. A package is a directory marked as a package by the presence of an __init__.py file.

Common Layout:

Often, packages have the following structure:

main.py
mypackage/
    __init__.py
    mymodule.py
    myothermodule.py

Example Code:

  • mymodule.py
# Exported function
def as_int(a):
    return int(a)

# Test function for module  
def _test():
    assert as_int('1') == 1

if __name__ == '__main__':
    _test()
  • myothermodule.py
# Exported function
def add(a, b):
    return as_int(a) + as_int(b)

# Test function for module  
def _test():
    assert add('1', '1') == 2

if __name__ == '__main__':
    _test()
  • main.py
from mypackage.myothermodule import add

def main():
    print(add('1', '1'))

if __name__ == '__main__':
    main()

When you run main.py or mypackage/mymodule.py, everything works smoothly. However, running mypackage/myothermodule.py fails due to the relative import:

from .mymodule import as_int

The Solution:

As Guido van Rossum explains, this failure is due to Python treating running scripts from within a package as an antipattern. The recommended solution is to avoid relative imports and use absolute imports instead:

from mypackage.mymodule import as_int

Alternative Approaches:

If you still prefer relative imports, you can use the -m option to specify the module to import, but it can be verbose and inconvenient:

python3 -m mypackage.myothermodule

Another alternative is to manipulate PYTHONPATH to include the parent directory of the package:

import sys
import os

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(SCRIPT_DIR))

from mypackage.mymodule import as_int

The above is the detailed content of Why Do Relative Imports in Python 3 Fail, and How Can I Fix Them?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn