One decorator turns any function into a durable parallel runner.
Project description
ParaWave: One decorator turns any function into a durable parallel runner.
Python 3.9+ License: MIT Tests
Parawave (short for parallel wave) turns any Python function — sync or async —
into a parallel, resumable runner with retry, rate limiting, and persistence.
Built for managing thousands of LLM API calls. Zero dependencies.
Install
pip install parawave
The base install has zero dependencies — just parawave and the Python standard library.
| Extra | Packages | What it enables | Install |
|---|---|---|---|
sqlite |
aiosqlite, aiofiles |
Persistent storage, cross-session resume | pip install parawave[sqlite] |
notebook |
nest_asyncio |
Jupyter / Colab support | pip install parawave[notebook] |
all |
All of the above | Everything | pip install parawave[all] |
Quick Start
import parawave
@parawave(
max_concurrency=20,
rate_limit=50,
retry=parawave.RetryPolicy(max_retries=3, backoff="exponential"),
)
async def enrich(city: str) -> dict:
response = await openai_client.chat.completions.create(
model="gpt-5.4-nano",
messages=[{"role": "user", "content": f"One fun fact about {city}"}],
)
return {"fact": response.choices[0].message.content}
result = enrich.run(data=[{"city": c} for c in cities])
[parawave] Starting run-e914e6b685e6 | 20 items | concurrency=20
[parawave] 5/20 (5 completed) | 0.8s | 6.3 items/s
[parawave] 12/20 (10 completed, 2 failed, 3 retried) | 1.4s | 8.6 items/s
[parawave] 18/20 (14 completed, 4 failed, 6 retried) | 1.9s | 9.5 items/s
[parawave] 20/20 (15 completed, 5 failed, 10 retried) | 2.1s | 9.6 items/s
[parawave] Completed run-e914e6b685e6 | 15/20 completed | 30 attempts, 10 retried, 5 failed | 2.1s
[parawave] To resume: .resume() | Cross-session: .resume("run-e914e6b685e6")
Some items failed — check what went wrong:
for item in result.failed:
print(f"{item.input['city']}: {item.error}")
Tokyo: RateLimitError: rate limit exceeded
Berlin: RateLimitError: rate limit exceeded
Seoul: APITimeoutError: request timed out
Mumbai: RateLimitError: rate limit exceeded
Cairo: APIConnectionError: connection reset
Resume to retry only the 5 failed items:
result = enrich.resume()
[parawave] Resuming run-e914e6b685e6 | 15/20 previously completed | concurrency=20
[parawave] 3/5 (3 completed) | 0.1s | 30.0 items/s
[parawave] 5/5 (5 completed, 1 retried) | 0.2s | 25.0 items/s
[parawave] Completed run-e914e6b685e6 | 20/20 completed | 2.3s
Works with sync functions too:
@parawave(max_concurrency=10)
def fetch(url: str) -> str:
return requests.get(url).text
With storage="sqlite", resume works across sessions — kill the process,
restart later, pick up where you left off.
Examples
| Notebook | Description |
|---|---|
| 01 — Quickstart | Core patterns — run, retry, resume, hooks, RunManager |
| 02 — Synthetic Data Pipeline | Rate and classify HuggingFace data with an LLM |
| 03 — Advanced Synthetic Pipeline | SharedState + Jinja templates for diverse synthetic data |
How it works
It's dead simple — three steps:
- Decorate any function with
@parawave() - Run with
.run(data=[...])— items fan out in parallel with bounded concurrency - Resume with
.resume()— retries only what failed
That's it. No daemon. No worker process. No message broker. Everything runs in your Python process.
More
Parawave also supports lifecycle hooks, shared state, warmup mode, result export (JSON, CSV), run tagging, and run history via RunManager. See the quickstart notebook for the full tour.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file parawave-0.1.0.tar.gz.
File metadata
- Download URL: parawave-0.1.0.tar.gz
- Upload date:
- Size: 402.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e4d5029444374b03d68e6c6d2ab470ca422cb26d6a60d8bd69ad6cd2b31aa20e
|
|
| MD5 |
3f9a468635170227c69c3e6b6b5e14e8
|
|
| BLAKE2b-256 |
a8629e43256b4b32bad7da2e0dd8a1060cf3430e7fe832e1d38d6cf17ac67399
|
File details
Details for the file parawave-0.1.0-py3-none-any.whl.
File metadata
- Download URL: parawave-0.1.0-py3-none-any.whl
- Upload date:
- Size: 39.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9f8802f0dbf1dee67d4cf81e483701dd23fd4c7a96088ee93d233ac6f81d73e
|
|
| MD5 |
797003c12868609419d9d212393156fc
|
|
| BLAKE2b-256 |
4750e20204b2b505ab27e91ca16b43b46a2fcb299fccb37865baea4ee12bef99
|