A self-contained skill for choosing Python concurrency mechanisms and making worker ownership, bounded admission, failure, cancellation, and shutdown explicit. It covers threads/processes/executors, asyncio structured lifetime, and CPython 3.14 free-threading and interpreter semantics without requiring sibling skills.
From a repository checkout:
mkdir -p ~/.claude/skills
cp -r python-concurrency ~/.claude/skills/Preserve local changes before replacing an existing installation. Copy the entire bundle so its references and license remain available. Installation adds instructions, not runtime dependencies; no package or framework is installed.
- "Choose threads, asyncio, or processes for this mixed I/O and CPU pipeline."
- "Review this TaskGroup for cancellation, partial effects, and worker cleanup."
- "Bound this queue without leaving an unbounded backlog of waiting tasks."
- "Explain why cancelling to_thread did not stop my blocking operation."
- "Make this worker pool portable to Python 3.14 forkserver and interpreter isolation."
| File | Load for |
|---|---|
| SKILL.md | Mechanism routing, contract workflow, high-risk pitfalls, completion evidence |
| Execution and coordination | Threads, synchronization, bounded queues, rate limiting, executors, process ownership/smoke recipe, deadlock diagnosis |
| Async lifecycle | TaskGroup failure, deadlines, cancellation, backpressure, queue accounting, thread bridging, shutdown |
| Runtime versions | Version gates, GIL probes, free-threaded builds, start methods, 3.14 interpreters/context flags |
From inside this bundle, including an isolated copied installation:
python3 -m doctest references/*.mdOr from the repository root:
python3 -m doctest python-concurrency/references/*.mdThese commands are verification instructions, not a claim of passing checks.
Run in an ordinary Python process, not an already-running notebook event loop.
All pycon fences are dependency-free and use Python 3.11+ except the explicitly
guarded interpreter check, which executes only on CPython 3.14+. The examples
exercise sibling failure/cleanup, zero-budget cancellation cleanup,
queue ordering/accounting/backpressure and error paths,
thread invariant protection, monotonic rate-limit boundaries, and the continued
lifetime of a thread after its asyncio awaiter is cancelled. They use local
primitives and bounded work, not a network service or arbitrary sleeps.
Thread/queue five-second deadlines are watchdogs, not latency assertions. An integration harness should put an outer process deadline around documentation checks too; event-loop timeouts cannot interrupt non-yielding code. Finite tests do not prove liveness under every schedule or establish performance.
The complete, clearly marked process recipe lives in
Execution and coordination.
Save that python fence as /tmp/python-concurrency-process-smoke.py, then run:
python3 /tmp/python-concurrency-process-smoke.py spawn
python3 /tmp/python-concurrency-process-smoke.py forkserverRun forkserver only where multiprocessing.get_all_start_methods() includes it.
These are real-process smoke commands, not part of doctest: they need an
importable writable script path, process creation permissions, and an outer
startup/shutdown timeout. The recipe checks empty/successful mapping and worker
exception propagation; it does not benchmark speedup or all shutdown failures.
The runtime reference also has an optional
InterpreterPoolExecutor recipe requiring CPython 3.14+, separately from its
guarded direct-interpreter doctest. A normal GIL-enabled run does not validate a
free-threaded deployment, extension compatibility, native thread safety, or
multi-core gains. Re-run the relevant checks on the actual build/dependencies.
Multiprocessing is unavailable on Android/iOS/WASI; interpreter/executor APIs
are unavailable on WASI. Preserve a consuming project's supported version floor.
Adapted from StructWeave-Algorithms Python content at commit
0b88a786ef09681717a805d9f7e0b195ab610f6c, rather than mutable branch URLs:
| Pinned source | Local coverage |
|---|---|
| 07 — Concurrency and async | All major topics: selection/GIL, thread primitives, queues, process pools/IPC/shared state, futures, asyncio scheduling/lifetime/limits, free threading/interpreters; interview ordering/queue/limiter/RW-lock material consolidated into standard-primitives guidance |
| 13 — Anti-patterns and best practices, concurrency section and async exercise | Compound updates, workload selection, blocking inside async functions, missing awaits, background ownership, shared async state |
| 14 — Interview traps, GIL implications and async/await gotchas | GIL limits, guarded process startup, await/scheduling distinction, host event loops, joining background tasks |
Consolidation/correction decisions:
Entrypoint concision: keep routing and lifetime policy always loaded; detailed mechanisms and runnable checks live in the directly linked references, with contents lists for navigation. The return-42 TaskGroup check was removed because the retained sibling-failure/cleanup and bounded-pipeline checks exercise meaningful TaskGroup behavior instead.
- Organize by lifetime and workload, not interview order. Standard queues, events, conditions, and locks replace custom blocking-queue/ordering machinery. Ordinary locks are the starting point instead of the source's reader-preference RW-lock sketch, whose fairness/starvation policy is unspecified.
- Do not promise observed races or speedups. An unlocked counter is not a portable atomic contract, but the source's exact claim that it will print a smaller count is not a reliable regression test on modern CPython. Processes, free-threading, and interpreters are candidates, not universal speed wins.
- Correct async race and lifetime claims. A plain built-in list append in
one loop thread is not itself a task-interleaving lost update. Invariants
spanning suspension need ownership/synchronization. Bare
create_task()is replaced with explicit supervision; no nested-loop patch is recommended. - Fix queue completion semantics. Account for sentinels too; distinguish
task_done()from business success. Do not wait for queue completion after a failed TaskGroup has discarded queued work. Bound backlog as well as workers. If bounded thread-queue publication fails, inspect the worker before reportingFull; otherwise a dead consumer's original error is masked. The regression includes trailing work after a rejected item, not just a singleton failure. - Separate rate from concurrency. A semaphore limits simultaneous work, not requests per time window; elapsed-time admission uses a monotonic clock.
- Use actual 3.14 APIs and limits. Interpreter
.exec()/.call()replace the source's nonexistent.run(). Interpreters need threads for parallelism, compatible extensions, and explicit destruction. They are not a security sandbox for the source's proposed untrusted-code use case. The isolated CPython 3.14.8 smoke exposedprepare_main(list)rejection: it requires shareable values, unlikecall's broader transfer support. The corrected example explicitly transfers JSON text and verifies that mutation of the decoded list does not alter the caller's original. - Distinguish build and runtime. Free threading began experimentally in 3.13 and is supported but optional in 3.14. GIL state, extension imports, process start defaults, and context flags are checked explicitly; thread context inheritance is not unconditional. Patch-level doc/runtime differences are recorded, including the 3.14.9 no-writable-temp forkserver fallback.
- Expand cancellation from first-party contracts. TaskGroup observes sibling
cleanup; deadlines do not roll back effects. Cancelling a
to_threadawaiter cannot stop an already-running callable; signal/observe its real lifetime.
Sensitive claims were checked against the Python documentation linked beside each reference. Those links are supporting sources, not dependencies required to use the installed skill. The original upstream MIT license is preserved verbatim in LICENSE.upstream.