Python, Development, Tools

Ditch Pip & Virtualenv: Meet UV, Your New Blazing-Fast Python Workflow

Discover UV, the Rust-powered Python package and project manager that's up to 100x faster and dramatically simplifies your development process.

Still juggling pip install, requirements.txt, and manually activating virtual environments? Prepare for a major upgrade. This article introduces UV, a revolutionary, all-in-one tool poised to replace your traditional Python workflow. If you write any Python code and crave speed and simplicity, y...…
Ditch Pip & Virtualenv: Meet UV, Your New Blazing-Fast Python Workflow
<a href="http://www.youtube.com/@TechWithTim">Tech With Tim</a> Tech With Tim Follow

Still juggling pip install, requirements.txt, and manually activating virtual environments? Prepare for a major upgrade. This article introduces UV, a revolutionary, all-in-one tool poised to replace your traditional Python workflow. If you write any Python code and crave speed and simplicity, you'll learn how UV integrates package installation, environment management, and even Python version handling into a single, lightning-fast command-line interface.

If you're still using pip or manually creating your own virtual environments, then you need to read this. In just a few minutes, I'm going to introduce a tool that could completely change your life if you write any code in Python. That tool is UV, a Python package and project manager that is almost 100 times faster than pip in certain situations.

Yes, you heard me correctly. You can see the example here from the [UV website][1].

UV consolidates tasks like managing virtual environments and installing dependencies (typically handled by pip) into one seamless tool. You'll see how it works, and I promise you it's significantly better than manually juggling virtual environments, requirements.txt files, and pip install. After learning about UV, it might just become the only tool you use from now on.

UV Installation & Setup

First things first, let's get UV installed. You can find detailed installation instructions in the [official documentation][2].

  • Mac/Linux: Use curl or wget:
    # Using curl
    curl -LsSf https://astral.sh/uv/install.sh | sh
  • Windows: Use PowerShell:
    irm https://astral.sh/uv/install.ps1 | iex
  • Using Pip (Cross-Platform): If you prefer using pip (or pip3 depending on your system):
    pip install uv
    # or
    pip3 install uv

Once installed, restart your terminal. To verify the installation, simply type:

uv

If you see output listing various UV commands, you're good to go! The [UV documentation][2] is excellent, but this guide will help clarify the basics and get you started quickly.

Managing Python Versions with UV

One of UV's powerful features is its ability to manage Python installations directly.

  • List available/installed versions: See which Python versions UV knows about and which you've already downloaded.

    uv python list

    Note: UV works with Python 3.8 and above.

  • Install a specific version: Download and install a Python version (e.g., 3.8).

    uv python install 3.8

    Notice how incredibly fast this is! UV is written in Rust and heavily optimized.

  • Find an installed version: Locate a specific installed version.

    uv python find 3.8
  • Uninstall a version: Remove a previously installed Python version.

    uv python uninstall <version_identifier>

Using UV for Single Scripts

UV simplifies running standalone Python scripts, especially those with dependencies or specific Python version requirements.

Let's start with a simple main.py:

# main.py
import sys
print(sys.version)
  • Run a script: Execute the script using the default Python found by UV.

    uv run main.py
  • Run with a specific Python version: Use the --python flag.

    uv run --python 3.9 main.py
    # Or be more specific
    uv run --python 3.9.21 main.py

    UV will use the specified version (if installed). No need to manually switch environments!

  • Run with temporary dependencies: What if your script needs packages like rich or requests?

    # main.py (updated)
    from rich import print
    import requests
    
    print("Hello from [bold magenta]Rich![/bold magenta]")
    # ... rest of your script using requests ...

    Instead of creating an environment and installing, use the --with flag. UV handles it temporarily for that run:

    uv run --python 3.9 --with rich --with requests main.py

    UV automatically installs the necessary packages (and caches them) before running your script. This is perfect for simple scripts without the overhead of full project setup.

Embedding Configuration in Scripts

Typing --python and --with repeatedly can be tedious. UV allows you to embed this configuration directly into your script file using a special comment block.

  • Initialize script configuration: Add Python version requirements.

    uv init --script main.py --python 3.9.21

    This adds the following block to the top of main.py:

    # /// script
    # requires-python = ">=3.9.21"
    # ///
    
    # Your script code follows
    import sys
    print(sys.version)

    You can use version specifiers like >= or pin an exact version with ==.

  • Add dependencies to the script config: Use uv add --script.

    uv add --script main.py rich
    uv add --script main.py requests

    This updates the script header:

    # /// script
    # requires-python = ">=3.9.21"
    # dependencies = [
    #  "rich",
    #  "requests"
    # ]
    # ///
    
    # Your script code follows
    from rich import print
    import requests
    # ...

    Now, simply running uv run main.py will automatically ensure the correct Python version is used and the listed dependencies are available (installed/cached if necessary) before execution.

Using UV for Python Projects

For larger projects, UV offers robust project management capabilities, replacing manual virtual environment creation and requirements.txt files.

  • Initialize a project: Navigate to your project directory and run:

    uv init

    This sets up a standard project structure:

    • .gitignore: Standard Git ignore file.
    • .python-version: Specifies the project's Python version (e.g., 3.10).
    • main.py: A sample entry point.
    • pyproject.toml: The central configuration file for metadata and dependencies (PEP 621 standard).
    • README.md: Project documentation.
    • .venv: A hidden directory containing the virtual environment managed by UV.

    Tip: Running uv init <directory_name> creates these files inside a new subdirectory named <directory_name>.

  • The pyproject.toml file: This file is key. It's more structured than requirements.txt and holds project details and dependencies.

    [project]
    name = "your-project-name"
    version = "0.1.0"
    description = "Add your description here."
    readme = "README.md"
    requires-python = ">=3.10" # Defined by uv init
    license = { file = "LICENSE" }
    
    dependencies = [
        # Dependencies added via 'uv add' will appear here
    ]
    
    [build-system]
    requires = ["hatchling"]
    build-backend = "hatchling.build"
  • Adding dependencies: Use uv add.

    uv add requests
    uv add "fastapi[all]" # Add extras

    UV resolves dependencies, installs them extremely quickly into the .venv, and updates the dependencies list in pyproject.toml with appropriate version specifiers.

  • Removing dependencies: Use uv remove.

    uv remove requests

    This uninstalls the package from .venv and removes it from pyproject.toml.

  • The uv.lock file: When you modify dependencies (uv add, uv remove, uv sync), UV creates or updates a uv.lock file. Much like package-lock.json (Node.js) or poetry.lock (Poetry), this file records the exact versions of all installed packages, including indirect (transitive) dependencies.

    Important: Commit uv.lock to your version control (e.g., Git). This ensures that other developers or CI/CD systems can run uv sync to recreate the exact same environment, guaranteeing reproducible builds.

  • Syncing the environment: The uv sync command ensures your .venv matches the state defined in pyproject.toml and uv.lock.

    # Install packages from lockfile / pyproject.toml into .venv
    uv sync 

    UV often runs sync implicitly. For example, if you manually edit pyproject.toml (e.g., add pygame) and then run uv run main.py, UV will detect the change, sync the environment (installing pygame), and then run your script. You can also run uv sync manually after pulling changes or modifying pyproject.toml directly.

  • Locking dependencies: If you only want to update the lock file without necessarily installing, use uv lock.

    uv lock
  • Handling Version Conflicts: Sometimes, adding a package might conflict with your Python version requirement. For example, trying uv add tensorflow in a project requiring Python 3.13 (if TensorFlow doesn't support it yet) will fail.

    1. Adjust Python Version: Edit pyproject.toml (e.g., requires-python = ">=3.10, <3.12") and the .python-version file (e.g., set content to 3.10).
    2. Retry Adding: Run uv add tensorflow again. UV will detect the Python change, adjust the environment, and attempt the installation.
  • Running Project Code: Once dependencies are set up, run your code using the managed environment:

    uv run main.py
    # Or run commands/modules installed in the venv
    uv run python -m pytest 

Conclusion

UV offers a significant leap forward for Python developers. By unifying package management, virtual environments, and even Python version installation into a single, blazing-fast tool built in Rust, it drastically simplifies workflows for both simple scripts and complex projects. Its compatibility with pyproject.toml aligns it with modern Python standards, while features like automatic environment syncing and lock files enhance reproducibility and collaboration.

If you're looking to speed up your development process and reduce tooling complexity, give UV a try. You might find it hard to go back!


Resources:

[1]: UV Homepage & Benchmarks [2]: UV Documentation