pytest-dev/pytest · error · ImportError
import error in
Error message
import error in {used}: {ex} What it means
An ImportError raised by _pytest.monkeypatch when resolving a dotted import path and an intermediate module fails to import, but the failure is for a different module than the one being imported (a transitive import error). The original exception is chained; the message wraps the inner error with the failing segment name so the user knows which part of the dotted path broke.
Solutions
- Read the chained ImportError: the inner message names the truly missing module.
- Install the missing dependency or fix the intermediate package's __init__.
- Verify the dotted path resolves in a plain Python session: `python -c 'import a.b.c'`.
- Patch a more specific path (closer to the leaf) to avoid importing a heavy/buggy intermediate.
Example fix
# before
monkeypatch.setattr('mypkg.sub.target', new_val)
# ImportError: import error in mypkg.sub: No module named 'missing_dep'
# after
# (install missing_dep, or patch where target already lives)
import mypkg.sub.target as t
monkeypatch.setattr(t, 'attr', new_val) Defensive patterns
Strategy: try-catch
Validate before calling
import importlib
def path_resolves(dotted: str) -> bool:
parts = dotted.split('.')
mod = parts[0]
try:
obj = importlib.import_module(mod)
except ImportError:
return False
for p in parts[1:]:
if not hasattr(obj, p):
return False
obj = getattr(obj, p)
return True Try / catch
try:
monkeypatch.setattr('a.b.c', value)
except ImportError as e:
# inspect chained exception for the truly missing module
print(f'transitive import failed: {e.__cause__}') Prevention
- Verify the dotted path imports in plain Python first.
- Install all transitive dependencies of the target package.
- Patch a more specific leaf to avoid heavy intermediate imports.
When it happens
Trigger: Calling `monkeypatch.setattr('a.b.c', value)` or `monkeypatch.delattr('a.b.c')` where importing `a` or `a.b` raises an ImportError whose offending module is not the segment being imported. For example, `a` imports fine but triggers an ImportError from a sibling module.
Common situations: Patching a path in a package whose __init__ has conditional imports; missing optional dependencies of an intermediate package; circular imports; wrong environment where a transitive dependency is absent.
Related errors
- must be absolute import path string, not
- object at has no attribute
- class fixtures not supported (maybe in the future)
- Error evaluating while defining fixture ' '. Expected a…
- errors during test teardown
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/5d856b5b5869b0d4.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/monkeypatch.py:88
found: object = importlib.import_module(used)
for part in parts:
used += "." + part
try:
found = getattr(found, part)
except AttributeError:
pass
else:
continue
# We use explicit un-nesting of the handling block in order
# to avoid nested exceptions.
try:
importlib.import_module(used)
except ImportError as ex:
expected = str(ex).split()[-1]
if expected == used:
raise
else:
raise ImportError(f"import error in {used}: {ex}") from ex
found = annotated_getattr(found, part, used)
return found
def annotated_getattr(obj: object, name: str, ann: str) -> object:
try:
obj = getattr(obj, name)
except AttributeError as e:
raise AttributeError(
f"{type(obj).__name__!r} object at {ann} has no attribute {name!r}"
) from e
return obj
def derive_importpath(import_path: str, raising: bool) -> tuple[str, object]:
if not isinstance(import_path, str) or "." not in import_path:
raise TypeError(f"must be absolute import path string, not {import_path!r}")
module, attr = import_path.rsplit(".", 1)View on GitHub (pinned to 0d6fbdeffa)