Python

Working with json

Writing json to file

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=4)

 

uv

uv: Python Environment & Package Manager

A single Rust binary that replaces pip, venv, pyenv, pipx, and poetry. It guarantees the right Python version and packages are present before running your code, so you stop managing virtual environments by hand.

Use it when: you want edit-and-run Python scripts (scrapers, automation, data jobs) without venv setup, manual activation, or a compile step.


Mental Model

uv sits between you and Python. Three modes, each storing its environment differently:

Mode When to use Where the env lives
Inline script (PEP 723) One .py file, ad-hoc scripts Ephemeral, in the global cache
Project Multi-file app, reproducible builds Visible .venv/ in the project folder
Tool install Installing a CLI globally (e.g. ruff) Isolated, like pipx

For a scraper / automation script, use inline script mode.


Install

# Linux / macOS (recommended, no existing Python needed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Installs the uv binary to:

Remember this path. cron and other minimal-environment runners do not include it in PATH.

Alternatives: pipx install uv, pip install uv, brew install uv. Update later with uv self update.


Inline Scripts (PEP 723)

Declare dependencies in a comment header at the top of the file. No requirements.txt, no project, no manual venv.

# scraper.py
# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx", "polars", "PyMySQL"]
# ///

import httpx, polars as pl, pymysql
# your code here

Run it:

uv run scraper.py

First run resolves, downloads, and builds a cached environment, then executes. Subsequent runs reuse the cache and start almost instantly. uv rebuilds the env only when the dependency list or Python version changes.

Add a dependency without hand-editing the header:

uv add --script scraper.py requests

Make the file directly executable:

#!/usr/bin/env -S uv run --script
chmod +x scraper.py
./scraper.py

Where the Cached venv Lives

Inline-script environments live in uv's global cache, not next to the file.

OS Default cache path
Linux $XDG_CACHE_HOME/uv or ~/.cache/uv
macOS ~/Library/Caches/uv
Windows %LOCALAPPDATA%\uv\cache

Find it on any machine:

uv cache dir

Housekeeping:

uv cache clean    # wipe entire cache
uv cache prune    # remove stale entries only
du -sh "$(uv cache dir)"   # check size (Linux/macOS)

For project mode, the env is instead a normal .venv/ in the project root, which you can inspect or delete directly.


Reproducibility (Pin Versions)

Unpinned dependencies will silently upgrade when a new release drops. For anything unattended, lock the versions:

uv lock --script scraper.py   # creates scraper.py.lock

Once locked, uv run, uv add --script, and uv tree --script reuse the pinned versions.

For a collection of related scripts you want to rebuild on another machine, use a project instead: a folder with pyproject.toml + uv.lock, then uv sync on the new machine reproduces the exact Python version and dependencies.


Running in Cron

It works. Two things bite people, both about the environment, not uv.

1. PATH

cron uses a stripped-down PATH (typically /usr/bin:/bin) that excludes ~/.local/bin, so a bare uv fails with "command not found". Use the absolute path (find it with which uv).

2. HOME / cache

uv needs HOME set to locate ~/.cache/uv. User crontabs usually set this correctly. System crontabs, containers, and service accounts may not, so set it explicitly.

# crontab -e
HOME=/home/youruser
UV_CACHE_DIR=/home/youruser/.cache/uv

*/15 * * * * /home/youruser/.local/bin/uv run /home/youruser/scrapers/scraper.py >> /home/youruser/logs/scraper.log 2>&1

Always redirect stdout and stderr to a log file, or failures vanish silently.

Cron checklist


Command Cheat Sheet

Command Does
uv run script.py Run a script (project or inline)
uv add --script script.py pkg Add a dependency to an inline script
uv lock --script script.py Pin versions for an inline script
uv init Create a new project
uv add pkg Add a dependency to a project
uv sync Rebuild a project env from the lockfile
uv python install 3.12 Install a specific Python version
uv tool install ruff Install a CLI tool globally (pipx-style)
uv cache dir Show the cache location
uv cache clean Wipe the cache
uv self update Update uv itself

Gotchas


Sources

Last reviewed: June 2026. Verify install URLs and cache behavior against the current docs if uv has had a major version bump.