Locking uv Script Dependencies

PEP 723 inline script dependencies let you declare deps directly in a script comment block and run with uv run. No virtualenv, no requirements file.

# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "requests>=2.31",
#   "rich",
# ]
# ///

The limitation is that inline metadata only supports standard version specifiers. There’s no mechanism for hash-pinning inside the script block itself.

Locking dependencies with hash verification

Version ranges leave you exposed to upstream changes — a new release can silently alter behavior or introduce a compromised package. uv can solve this by generating a lockfile with pinned versions and hashes:

uv lock --script my_script.py

This produces my_script.py.lock containing pinned versions and hashes for every resolved dependency. The lockfile travels with the script and can be committed to version control.

Enforcing the lockfile at runtime

By default, uv run will use the lockfile if one exists. Two flags give you stricter control:

# Fails if the lockfile is absent or out of sync with the inline deps
uv run --locked my_script.py

# Uses the lockfile as-is — no resolution, no network calls
uv run --frozen my_script.py

--locked is appropriate for local development: it catches drift between your inline deps and the lockfile. --frozen is better suited to CI, where you want to prohibit any resolution entirely and guarantee the environment matches what was committed.

Martin Mahner

About the author

Martin Mahner

Martin is an active member and contributor to the Django community where he is mostly known as bartTC. It's likely that you have stumbled over one of his apps or snippets. Besides coding, Martin also has …

View Martin's profile