Skip to main content

Mastering UV Scripts: Simplifying Python Development with UV Package Manager

4 min read

UV has revolutionized Python package management with its incredible speed and simplicity. One of its most powerful features is the ability to create and run self-contained Python scripts with inline dependency management, making development faster and more efficient.

In this post, I’ll show you how to leverage UV’s script functionality to streamline your Python development workflow, from creating simple scripts to managing complex dependencies.

Creating Your First UV Script

Let’s start with a simple example. First, create a script with inline metadata:

uv init --script hello.py --python 3.12

This creates a script file with the proper header structure. You can also generate the header for an existing file:

uv init --script http://script.py

Now add dependencies to your script:

uv add --script hello.py requests rich

Your script will now include inline metadata like this:

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

import requests
from rich.console import Console

console = Console()
response = requests.get("https://api.github.com/users/astral-sh")
console.print(f"UV by Astral has [bold green]{response.json()['public_repos']}[/bold green] public repos!")

Run your script with:

uv run hello.py

UV automatically creates an isolated environment, installs the dependencies, and executes your script!

Advanced Script Features

Executable Scripts with Shebang

Make your scripts directly executable by adding a shebang line:

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx"]
# ///

import httpx

print(httpx.get("https://example.com"))
chmod +x my_script.py
./my_script.py

Running Scripts with Temporary Dependencies

Need to test with different package versions? Use the --with flag:

uv run --with httpx==0.26.0 my_script.py
uv run --with "pandas>=2.0" data_analysis.py

Running Scripts from URLs or stdin

UV can even run scripts directly from remote sources:

echo 'print("Hello from UV!")' | uv run -

My Personal Development Environment Shortcuts

Here’s my custom function that I use to quickly initialize development environments with UV:

function uvnit() {
    VENV_PATH="./.venv"

    # Check if the venv folder exists
    if [ -d "$VENV_PATH" ]; then
        echo "Activating existing Python virtual environment..."
        source "$VENV_PATH/bin/activate"
    else
        echo "Creating Python virtual environment..."
        uv init .
        uv venv "$VENV_PATH"
        source "$VENV_PATH/bin/activate"
    fi
}
alias pyoff="deactivate"

This function is my go-to shortcut for initializing development environments. It:

  • Checks if a virtual environment already exists
  • If not, creates a new UV project and virtual environment
  • Activates the environment automatically
  • I pair it with pyoff alias to quickly deactivate environments

Add these to your .bashrc or .zshrc for instant access to UV-powered development environments!

Comparing UV Scripts to Traditional Approaches

AspectUV ScriptsTraditional venv + pip
Setup Speed✓ Instant script execution
✓ Automatic dependency resolution
✓ Built-in caching
✗ Manual venv creation
✗ Separate pip installs
✗ No built-in caching
Dependency Management✓ Inline metadata
✓ Version pinning
✓ Automatic isolation
✗ External requirements.txt
✗ Manual version management
✗ Potential conflicts
Performance✓ Rust-powered speed
✓ Parallel installation
✓ Smart caching
✗ Python-based tools
✗ Sequential installs
✗ Limited caching
Portability✓ Self-contained scripts
✓ No external config files
✓ Easy sharing
✗ Multiple files needed
✗ Manual setup required
✗ Environment reproduction issues
Development Experience✓ Zero-config execution
✓ Immediate script running
✓ Built-in best practices
✗ Multi-step setup
✗ Manual activation needed
✗ Easy to forget steps

Best Practices for UV Scripts

  • Use inline metadata: Keep dependencies close to your code for better maintainability
  • Pin Python versions: Specify requires-python for consistency across environments
  • Leverage caching: UV’s intelligent caching makes repeated runs lightning-fast
  • Make scripts executable: Use shebang lines for direct script execution
  • Version your dependencies: Be specific with version constraints for reproducible results
  • Use temporary dependencies: Experiment with --with before committing to script metadata

Real-World Use Cases

UV scripts excel in various scenarios:

  • Data analysis scripts: Quickly prototype with pandas, numpy, and visualization libraries
  • API integrations: Test API endpoints with httpx or requests without environment setup
  • Automation tasks: Create self-contained scripts for CI/CD pipelines
  • Learning and experimentation: Try new libraries without polluting your global environment
  • Microservices: Deploy lightweight, self-contained Python services

Why UV Scripts Matter for Modern Development

In today’s fast-paced development environment, UV scripts provide the perfect balance of simplicity and power. They eliminate the friction of environment management while maintaining the isolation and reproducibility that professional development demands.