pythonpath.rst

Overview

This documentation file explains how pytest manages its import mechanisms related to Python's `sys.path` and [PYTHONPATH](/projects/286/67459) during test discovery and execution. Specifically, it details the different *import modes* pytest supports when importing test modules and `conftest.py` configuration files, how these modes affect `sys.path`, module names, and test isolation, and the scenarios where these behaviors are relevant.

This file serves as a guide for pytest users and developers to understand the underlying import logic, avoid common pitfalls related to Python package layouts, and configure pytest appropriately for their project structure and testing needs.


Import Modes

pytest needs to import test modules and `conftest.py` files to execute tests. Because Python import semantics can be complex in test environments, pytest offers three import modes selectable via the `--import-mode` command-line flag:

1. prepend (default)

2. append

3. importlib


Important Notes


Usage Scenarios: prepend and append Modes

Test Modules and conftest.py Inside Packages

Given this directory structure:

root/
|- foo/
   |- __init__.py
   |- conftest.py
   |- bar/
      |- __init__.py
      |- tests/
         |- __init__.py
         |- test_foo.py

Running:

pytest root/

Standalone Test Modules and conftest.py Files

Given this directory structure:

root/
|- foo/
   |- conftest.py
   |- bar/
      |- tests/
         |- test_foo.py

Running:

pytest root/

Invoking pytest: pytest vs python -m pytest


Implementation Details and Algorithms


Interactions with Other System Components


Example Usage

Run pytest with the default import mode (`prepend`):

pytest --import-mode=prepend tests/

Run pytest without modifying `sys.path` (unique module names, isolated imports):

pytest --import-mode=importlib tests/

Run pytest to test installed packages by appending test directories to the end of `sys.path`:

pytest --import-mode=append tests/

Mermaid Diagram: Import Mode Structure and Workflow

flowchart TD
    A[pytest starts test import] --> B{Select import mode}
    B -->|prepend (default)| C[Insert test module dir at start of sys.path]
    B -->|append| D[Insert test module dir at end of sys.path]
    B -->|importlib| E[Import module directly without sys.path changes]

    C --> F[Import module with importlib.import_module]
    D --> F
    E --> G{Try import by canonical name}
    G -->|Success| H[Return imported module]
    G -->|Fail| I[Import module with unique name using importlib]
    I --> J[Add to sys.modules with unique name]
    J --> H

    F & H --> K[pytest executes tests]

    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style E fill:#f96,stroke:#333,stroke-width:2px

References


Summary

This document clarifies how pytest manages Python imports for test modules and configuration files, explaining the implications of different import modes and directory layouts. Understanding this is crucial for writing robust tests, organizing test code correctly, and avoiding common import-related errors in pytest-based projects.