# uv - Python Package Manager
## Determining Which Python Interpreter is Used
### Quick checks
**Find which Python uv will use:**
```bash
uv python find
```
Prints the exact interpreter path `uv` would use (considering `.python-version`, `.venv`, etc.).
**See what uv run actually used:**
```bash
uv run python -c "import sys; print(sys.executable); print(sys.prefix)"
```
- `sys.executable` → Python binary being used
- `sys.prefix` → venv location
**Force a specific interpreter:**
```bash
uv run --no-project -p /path/to/python python --version
```
`-p/--python` lets you specify an interpreter; `--no-project` ignores project constraints.
### How uv selects Python
uv discovers interpreters in this order:
1. Directly provided path (`-p/--python`)
2. Spawning interpreter (when using `python -m uv`)
3. Activated venv (`VIRTUAL_ENV`)
4. Venv in current directory (`./.venv`)
5. Interpreter on `PATH`
### Environment variables
- `VIRTUAL_ENV` → if set, uv will use that environment
- `uv pip install --python /path/to/python` → target specific environment
- `uv pip install --system` → use system Python
- In projects, uv automatically finds and uses `./.venv`
## Running with Ad-hoc Dependencies (`--with`)
`--with` injects packages into the run environment without adding them to a project.
**Single dependency:**
```bash
uv run --with rich example.py
```
**Version constraints:**
```bash
uv run --with 'rich>12,<13' example.py
```
**Multiple dependencies (repeat the flag):**
```bash
uv run --with requests --with rich example.py
```
Inside a project, `--with` packages supplement the project's existing dependencies. Use `--no-project` to skip project deps entirely:
```bash
uv run --no-project --with requests script.py
```
### Quick one-liners with `python -c`
Combine `--with` and `python -c` for throwaway snippets that need a package:
```bash
uv run --with httpx python -c "import httpx; print(httpx.get('https://example.com').status_code)"
```
```bash
uv run --with rich python -c "from rich import print; print('[bold green]hello[/bold green]')"
```
Multiple deps work too:
```bash
uv run --with requests --with beautifulsoup4 python -c "
import requests, bs4
html = requests.get('https://example.com').text
print(bs4.BeautifulSoup(html, 'html.parser').title.string)
"
```
### With tools (`uvx` / `uv tool run`)
Same flag works for CLI tools — handy for plugins:
```bash
uvx --with mkdocs-material mkdocs serve
```
Permanent tool install with extras:
```bash
uv tool install mkdocs --with mkdocs-material
```
## Keeping Tools Up to Date
```bash
uv tool list # see installed tools and versions
uv tool upgrade --all # upgrade all tools installed via uv tool install
uv tool upgrade ty # upgrade a specific tool
```
## Inline Script Dependencies (`--script` / PEP 723)
Single-file scripts can declare their own dependencies via PEP 723 metadata, so anyone can run them with just `uv run`.
### Creating a script with metadata
```bash
uv init --script example.py --python 3.12
```
### Adding dependencies to a script
```bash
uv add --script example.py 'requests<3' 'rich'
```
This produces an inline metadata block at the top of the file:
```python
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich import print
...
```
### Running it
```bash
uv run example.py
```
uv reads the metadata, installs the deps into an ephemeral environment, and runs the script. No virtualenv setup needed.
### Making scripts directly executable
Add a shebang so the script can run standalone:
```python
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["requests"]
# ///
import requests
...
```
Then:
```bash
chmod +x example.py
./example.py
```
### Locking a script
```bash
uv lock --script example.py
```
Creates `example.py.lock` alongside the script, pinning exact versions (with hashes) of all dependencies and their transitive deps. Each script gets its own independent lockfile, so multiple scripts in the same folder lock separately:
```text
my-folder/
├── example.py
├── example.py.lock # pins requests + deps
├── other.py
└── other.py.lock # pins rich + deps
```
When `uv run example.py` finds a lockfile, it uses those pinned versions. If the lockfile is missing or the inline metadata has changed, uv resolves fresh.
> **Note:** When inline metadata is present, project dependencies are ignored — `--no-project` is not needed.