pytest
import error
Python
module import
troubleshooting

pytest cannot import module while python can

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

This problem usually means pytest and your normal Python invocation are not running with the same import path assumptions. The fix is rarely to hack sys.path; it is usually to make the project layout and test invocation reflect how the package is meant to be installed.

Why Python and pytest Can Disagree

When you run a file directly, Python seeds sys.path from the script location and the current environment. pytest also imports test modules, conftest.py, and application code during collection, and its import mode can change how directories are inserted into sys.path.

That is why these two commands can behave differently:

bash
python app.py
pytest

The first runs one file. The second discovers and imports many files from the project tree.

The quickest sanity check is to compare:

bash
python -m pytest -q
pytest -q

Running python -m pytest ensures the same interpreter that can import your package is also the one launching pytest. If one works and the other does not, you likely have an environment or path mismatch rather than a broken module.

The Reliable Fix: Install Your Package and Use a Clear Layout

The most robust setup is a src layout with an editable install:

text
1project/
2  pyproject.toml
3  src/
4    myapp/
5      __init__.py
6      service.py
7  tests/
8    test_service.py

Then install it into your virtual environment:

bash
python -m pip install -e .
python -m pytest

A minimal pyproject.toml can look like this:

toml
1[build-system]
2requires = ["setuptools>=68", "wheel"]
3build-backend = "setuptools.build_meta"
4
5[project]
6name = "myapp"
7version = "0.1.0"

And your test imports the package the same way production code would:

python
1from myapp.service import add
2
3
4def test_add():
5    assert add(2, 3) == 5

This avoids the fragile pattern where tests only pass because the current working directory happens to expose source files directly.

Things That Commonly Break Imports

A few patterns cause this issue again and again:

  • running pytest from a different interpreter than the one where dependencies are installed
  • naming a test file the same as a package module
  • relying on the repository root being on sys.path
  • mixing flat-layout source code with ad hoc relative imports
  • missing __init__.py in a regular package where one is required

You can inspect what pytest sees with a temporary debugging test:

python
1import sys
2
3
4def test_debug_import_path():
5    for entry in sys.path:
6        print(entry)

That is useful for diagnosis, but it should not become the permanent solution.

Use pytest Configuration Carefully

pytest also supports different import modes. In some projects, switching import mode can reduce path surprises:

bash
python -m pytest --import-mode=importlib

This can help when test module names clash or when path mutation causes confusing imports. Still, changing the import mode is a secondary fix. A properly packaged project is the primary fix.

If you need test settings, keep them in configuration instead of shell folklore:

toml
[tool.pytest.ini_options]
testpaths = ["tests"]

That makes test discovery explicit without rewriting import semantics behind the scenes.

Prefer Absolute Imports Inside Tests

Avoid importing application code through relative paths from the test directory. This is brittle:

python
from ..src.myapp.service import add

Use the package name instead:

python
from myapp.service import add

If that import fails, it is telling you something useful: the package is not installed or not laid out the way production code expects.

Common Pitfalls

The biggest pitfall is fixing the symptom with sys.path.insert(0, "..") inside tests. That can make the suite pass locally while hiding packaging bugs that reappear in CI, IDEs, and deployment tooling.

Another frequent issue is using the global pytest executable while the project dependencies live in a virtual environment. python -m pytest removes that ambiguity.

File naming collisions are also easy to miss. A file named pytest.py, requests.py, or myapp.py can shadow the package you intended to import.

Finally, namespace packages and regular packages behave differently. If you are not intentionally building a namespace package, include __init__.py where appropriate.

Summary

  • 'pytest import failures usually come from path or environment differences, not magic.'
  • Prefer python -m pytest so the right interpreter runs the tests.
  • Package the project properly and install it with pip install -e ..
  • Use absolute imports from the package name, not path hacks.
  • Treat sys.path workarounds as diagnostics, not as architecture.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.