This document describes Python version compatibility for Tach.
| Python Version | Status | Notes |
|---|---|---|
| 3.10 | Supported | Minimum supported version |
| 3.11 | Supported | Full feature support |
| 3.12 | Supported | Required for PEP 669 coverage |
| 3.13 | Supported | Includes mimalloc TLS handling |
| 3.13t | Experimental | Free-threading build (see below) |
| 3.14 | Supported | Latest release (Oct 2025) |
| 3.9 and below | Unsupported | May work but not tested |
| Feature | Minimum Version | Notes |
|---|---|---|
| Core test execution | 3.10 | Basic functionality |
| Zero-overhead coverage | 3.12 | Uses PEP 669 (Low-Impact Monitoring) |
| mimalloc TLS restoration | 3.13 | Self-calibrating offset discovery |
Tach uses PyO3 0.27 for Rust-Python integration.
| Implementation | Version | Status |
|---|---|---|
| CPython | 3.7+ | Supported by PyO3 |
| PyPy | 7.3 (Python 3.11+) | Experimental |
| GraalPy | 24.0+ (Python 3.10+) | Untested |
Note: While PyO3 supports CPython 3.7+, Tach requires Python 3.10+ for its own functionality.
PyPy is an alternative Python implementation with a JIT compiler. PyO3 0.27 provides experimental support for PyPy 7.3 (targeting Python 3.11+).
Current Status: Untested with Tach.
Known Considerations:
- PyPy has a different memory model than CPython
- The userfaultfd-based snapshot/restore may behave differently
- C extension compatibility varies
- JIT compilation may interact unexpectedly with Tach's isolation model
Recommendation: PyPy support is experimental. If you need to test PyPy-based projects, consider using --no-isolation mode and report any issues encountered.
GraalPy is the GraalVM-based Python implementation.
Current Status: Untested with Tach.
GraalPy has a fundamentally different runtime architecture that may not be compatible with Tach's low-level process manipulation.
PEP 703 introduces a build configuration (--disable-gil) that allows CPython to run without the Global Interpreter Lock (GIL). This is available as an experimental feature starting with Python 3.13.
Free-threaded Python builds are identified as python3.13t (the "t" suffix indicates free-threading).
- No Global Interpreter Lock: Multiple threads can execute Python bytecode simultaneously
- Memory Model: Uses biased reference counting instead of the traditional reference counting
- Allocator: Replaces pymalloc with mimalloc for thread-safe memory allocation
- C Extensions: Must explicitly declare thread-safety; otherwise, the GIL is re-enabled
Tach's current architecture relies on several assumptions that may be affected:
flowchart TB
subgraph Current["CURRENT MODEL (GIL-based)"]
direction TB
A[Zygote Process] --> B[Fork Workers]
B --> C[Memory Snapshot]
C --> D[Test Execution]
D --> E[Memory Restore]
note1["GIL ensures single-threaded<br/>Python execution per process"]
end
subgraph FreeThreaded["FREE-THREADING CONSIDERATIONS"]
direction TB
F[Multiple Threads] --> G[Concurrent Execution]
G --> H[Memory Contention]
H --> I[Snapshot Complexity]
note2["No GIL means true<br/>concurrent Python threads"]
end
Considerations:
| Aspect | Current (GIL) | Free-Threading |
|---|---|---|
| Thread Safety | GIL serializes access | Explicit synchronization required |
| Memory Snapshots | Single-threaded state | Must handle concurrent modifications |
| Reference Counting | Simple increment/decrement | Biased reference counting |
| Allocator | pymalloc/jemalloc | mimalloc (thread-local) |
| C Extensions | Assume GIL protection | Must declare Py_mod_gil |
-
Snapshot Timing: Without the GIL, determining a safe point to capture memory state becomes more complex. Multiple threads may be modifying Python objects concurrently.
-
Reference Count Integrity: The biased reference counting system in free-threaded Python uses deferred reference counting for some objects, which may affect snapshot consistency.
-
mimalloc Thread-Local State: Free-threaded Python uses mimalloc with thread-local allocation buffers (TLABs). Tach already handles mimalloc TLS restoration for Python 3.13+, but concurrent thread allocation patterns may introduce new edge cases.
-
Extension Compatibility: PyO3-based extensions (including Tach itself) must declare free-threading compatibility using
#[pymodule(gil_used = false)]or the GIL will be re-enabled at runtime.
For free-threaded Python support in Tach:
- Phase 1 (Current): Document implications and monitor Python 3.13t ecosystem maturity
- Phase 2 (Future): Test basic functionality with
--no-isolationmode - Phase 3 (Future): Investigate snapshot-safe synchronization primitives
- Phase 4 (Future): Implement full free-threading support if demand exists
PyO3 0.23+ provides experimental support for free-threaded Python:
- Use
#[pymodule(gil_used = false)]to declare thread-safety - Use
Py_GIL_DISABLEDfor conditional compilation - Replace
static mutwithPyOnceLockorMutexfor shared state - abi3 (limited API) is not compatible with free-threading
Note: Extensions that do not explicitly declare free-threading support will cause the interpreter to re-enable the GIL at runtime, effectively falling back to the traditional model.
Python 3.14 was released on October 7, 2025 and is fully supported by Tach.
| Feature | Status | Notes |
|---|---|---|
| PEP 649: Deferred Annotations | Compatible | Annotations evaluated lazily (now default) |
| PEP 750: Template Strings | Compatible | New t-strings syntax supported |
| Improved error messages | Compatible | Better exception formatting |
sys.monitoring improvements |
Compatible | Coverage collection works correctly |
| Free-threaded build availability | Untested | 3.14t builds not yet tested |
- All core functionality works identically to Python 3.13
- Coverage collection via PEP 669 (
sys.monitoring) functions correctly - No changes required to Tach configuration
- mimalloc TLS handling continues to work as in 3.13
See the Python 3.14 release notes and PEP 745 (Release Schedule) for details.
Tach automatically detects the Python version at runtime:
# Check Python version
python --version
# Verify Tach sees the correct Python
./target/release/tach-core self-testThe self-test command reports the detected Python version and validates system compatibility.
If Tach uses the wrong Python version:
-
Ensure
PYO3_PYTHONis set during build:export PYO3_PYTHON=$(which python) cargo build --release
-
Verify the virtual environment is active:
source .venv/bin/activate which python
Coverage requires Python 3.12+ for PEP 669 support:
python --version # Must be 3.12+
./target/release/tach-core --coverage .If using Python 3.10 or 3.11, coverage collection is disabled.
Python 3.13 switched from pymalloc to mimalloc. If you encounter memory-related issues:
- Verify Tach version supports Python 3.13
- Check for TLS restoration errors in verbose output (
-vv) - Report issues with detailed system information
- Development Guide - Build and test instructions
- Configuration - Runtime configuration options
- Troubleshooting - Common issues and solutions
- Architecture: Snapshot - Memory snapshot internals