A small, production-style async Python playground built to learn:
- Modern
asynciopatterns - Async HTTP with
httpx - Concurrency vs parallelism (threads vs processes)
- Timeouts & cancellation
- A tiny
FastAPIservice with background jobs - Project best practices (pyproject, linters, tests, Docker, Makefile)
- 🧠 Async basics:
async/await, tasks,asyncio.gather, semaphores - 🌐 Async HTTP client using
httpx.AsyncClient - 🔧 Config via environment /
.envusingpydantic-settings - 📜 Logging with configurable log level
- 🚀 FastAPI API:
POST /fetch→ concurrent HTTP fetchPOST /jobs→ starts a background jobGET /jobs/{id}→ check job status / result
- 🔬 Testing with
pytest+pytest-asyncio - 📦 Containerized with Docker
- 🛠️ Developer-friendly Makefile + shell scripts
- Python 3.11+
- Make (optional, for using the Makefile)
- Docker (optional, for containerization)
-
Clone the repository:
git clone https://github.com/Conacious/python-async-playground.git cd python-async-playground -
Create a virtual environment:
make venv # Or manually: python -m venv .venv -
Install dependencies:
make deps # Or manually: pip install -e ".[dev]"
The application uses pydantic-settings to load configuration from environment variables or a .env file.
-
Create a
.envfile (optional, defaults are provided):cp .env.example .env # If you have an example, otherwise just create one -
Available Environment Variables:
Variable Default Description ASYNC_PLAYGROUND_LOG_LEVELINFOLogging level (DEBUG, INFO, WARNING, ERROR) ASYNC_PLAYGROUND_HTTP_TIMEOUT10.0Timeout for HTTP requests in seconds ASYNC_PLAYGROUND_HTTP_MAX_CONCURRENT5Max concurrent HTTP requests ASYNC_PLAYGROUND_HTTP_GLOBAL_TIMEOUTNoneGlobal timeout for batch operations
You can run the application in different modes using the CLI or start the API server.
Run the async-playground command (installed via pip install -e .) or use python -m async_playground.
-
HTTP Fetch Demo (Concurrent requests):
make cli-http # Or: python -m async_playground --mode http -
Async Sleep Demo (Basic asyncio mechanics):
make cli-sleep # Or: python -m async_playground --mode sleep -
Blocking Tasks Demo (Threads vs Processes):
make cli-blocking # Or: python -m async_playground --mode blocking
Start the FastAPI server:
make api
# Or: uvicorn async_playground.api:app --reloadThe API will be available at http://localhost:8000.
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
You can use the helper scripts in scripts/ or curl:
-
Fetch URLs concurrently:
./scripts/call_fetch.sh https://www.python.org https://fastapi.tiangolo.com
-
Start a background job:
./scripts/start_job.sh https://www.python.org
-
Check job status:
./scripts/check_job.sh <JOB_ID>
async_playground/
├─ src/
│ └─ async_playground/
│ ├─ __init__.py
│ ├─ __main__.py # enables: python -m async_playground
│ ├─ cli.py # CLI entrypoint
│ ├─ api.py # FastAPI app
│ └─ core/
│ ├─ config.py # Settings via pydantic-settings
│ ├─ http_client.py # Async httpx client + concurrency
│ ├─ example_async.py # Simple asyncio demo
│ ├─ blocking_tasks.py # CPU-bound + threads/processes demo
│ ├─ logging_utils.py # Logging configuration
│ └─ ...
│
├─ tests/ # pytest + pytest-asyncio tests
├─ scripts/ # helper bash scripts to call the API
├─ pyproject.toml # project + tool configuration
├─ Makefile # common developer commands
├─ Dockerfile # container image definition
├─ .dockerignore
├─ .env # local configuration (not for production)
└─ README.md
- Format code:
make format(Black) - Lint code:
make lint(Ruff) - Type check:
make typecheck(Mypy) - Run tests:
make test(Pytest) - Run all checks:
make check
Build and run the containerized application.
-
Build image:
make docker-build
-
Run container:
make docker-run
The API will be accessible at
http://localhost:8000.