Skip to main content

pytest-subproc

Run marked pytest test functions in an isolated subprocess to protect the main process from crashes caused by C++ panics, segfaults, or hangs.

Installation

pip install pytest-subproc

Usage

Mark any test with @pytest.mark.subproc to run it in a subprocess:

import pytest

@pytest.mark.subproc
def test_isolated():
    assert True

Parameters

@pytest.mark.subproc(timeout=None, condition=None)

Parameter Type Default Description
timeout float None Timeout in seconds. Kills the subprocess if the test exceeds this limit. Falls back to subproc_default_timeout ini option.
condition bool or () -> bool True When falsy, the test runs in the main process normally. Useful for conditional isolation (e.g., only in CI).
@pytest.mark.subproc(timeout=30)
def test_with_timeout():
    ...

@pytest.mark.subproc(condition=lambda: os.environ.get("CI") == "true")
def test_ci_only():
    ...

@pytest.mark.subproc(timeout=10, condition=False)
def test_never_subprocess():
    ...

Configuration via pyproject.toml / pytest.ini

[tool.pytest.ini_options]
subproc_default_timeout = 30

Or on the command line:

pytest --subprocess-timeout=30

Module-level configuration

Set defaults for all @pytest.mark.subproc tests in a directory tree by calling pytest_subproc methods in a conftest.py:

import pytest_subproc

# Default timeout (lowest priority: marker > CLI > ini > this)
pytest_subproc.config_default_timeout(30)

# Default condition for spawning (lowest priority: marker > this)
pytest_subproc.config_global_enabled(True)
pytest_subproc.config_global_enabled(lambda: os.environ.get("CI") == "true")  # callable

@pytest.mark.timeout interaction

When a test has both @pytest.mark.subproc(timeout=5) and @pytest.mark.timeout(3), the shorter value (3s) is used as the subprocess timeout. This prevents pytest-timeout from killing the main process while the subprocess is still running — our plugin cancels pytest-timeout's timer and enforces the effective timeout on the subprocess itself.

@pytest.mark.subproc(timeout=5)
@pytest.mark.timeout(3)       # ← effective timeout (shorter wins)
def test_obey_the_shorter():
    ...

How It Works

  1. Interceptionpytest_runtest_protocol (tryfirst) takes over the protocol for subproc-marked tests.

  2. Isolated run — The main process spawns a child that runs pytest.main([nodeid, --rootdir, ...]) for that single test. The full lifecycle (conftest loading, fixture resolution, setup, call, teardown) happens inside the subprocess.

  3. Timeout & cleanup — The child is created with start_new_session so the entire process group (including test‑spawned children) is killed when the timeout fires.

  4. Result — A plugin inside the subprocess captures the outcome and exception; these are pickled to a temp file. The parent re‑raises the exception so xfail, skip, etc. work as expected.

  5. Config parityasyncio_mode, xfail_strict and other ini settings are forwarded to the subprocess via --override-ini.

Comparison with pytest-forked

pytest-subproc pytest-forked
Mechanism Spawns a new Python process (subprocess) Forks the existing process (os.fork)
Fixtures Re‑evaluated in the child (full conftest + fixture resolution) Inherited from parent via copy‑on‑write
Windows ✅ Supported ❌ Not available
Crash isolation Full — the child has its own PID and memory space; a segfault cannot reach the parent Partial — forked process shares file descriptors and some kernel state with the parent
Timeout Built‑in timeout parameter on the marker, with process‑tree termination Only via external pytest-timeout plugin
Process‑tree cleanup Kills the entire process group on timeout (os.killpg / taskkill /T) No automatic child‑process cleanup
Startup cost Moderate — a new Python interpreter starts and runs pytest.main for one test Low — fork is (mostly) copy‑on‑write
pytest-xdist ✅ Compatible ✅ Compatible

Feature Compatibility

Feature Status
Python >= 3.7
Function, session, and module-level fixtures
stdout/stderr captured and shown on failure
pytest.mark.asyncio + asyncio_mode = "auto"
@pytest.mark.parametrize
@pytest.mark.xfail(raises=...)
Custom exception pickling / re-raising
flaky retries
pytest-timeout signal handling
pytest-cov coverage passthrough

Requirements

  • Python >= 3.7
  • pytest >= 7.0

License

MIT

Release files for pytest-subproc 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-subproc 0.1.2
File Size Uploaded
pytest_subproc-0.1.2.tar.gz 17.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-subproc 0.1.2
File Interpreter ABI Platform
pytest_subproc-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 27.3 kB

Release files / pytest_subproc-0.1.2.tar.gz

Download URL pytest_subproc-0.1.2.tar.gz
Size 17.8 kB
Tags Source
SHA-256 checksum
How to use checksums
60f266edbd380b1e7090ce8790dcc3c983b2d56e9cffbc00dbcc2e076a3fac0f
BLAKE2b-256 checksum
How to use checksums
50f61249e990751a2f4b36faf5923aa2dbfa669ae5d96b113fb276152a77fee3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release files / pytest_subproc-0.1.2-py3-none-any.whl

Download URL pytest_subproc-0.1.2-py3-none-any.whl
Size 9.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c0bc7212cebac5325f3a70276177a7a1f4a2fa5d23ff8c5bdb452e5ab4b60403
BLAKE2b-256 checksum
How to use checksums
baa264319d4441f21bde7c5299dba36a596fb7212f7d64f6ce6f8180e96ad5c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page