Python UV: The Ultimate Guide to the Fastest Python Package Manager
Learn how to use UV, the fastest Python package manager in 2026. Discover 10x faster dependency management, virtual environments, and seamless migration from pi
UV is a modern, high-performance Python package manager and installer written in Rust. It serves as a drop-in replacement for traditional Python package management tools like pip, offering significant improvements in speed, reliability, and dependency resolution.
This tool represents a new generation of Python package managers, designed to address common pain points in the Python ecosystem such as slow installation times, dependency conflicts, and environment management complexity. UV achieves this through its innovative architecture and efficient implementation, making it 10-100 times faster than traditional package managers.
Key features that make UV stand out:
Lightning-fast package installation and dependency resolution
Compatible with existing Python tools and workflows
Built-in virtual environment management
Support for modern packaging standards
Reliable dependency locking and reproducible environments
Memory-efficient operation, especially for large projects
Whether working on small personal projects or managing large-scale Python applications, UV provides a robust and efficient solution for package management. In this tutorial, we will cover all essential aspects of UV so you can start using it immediately.
TL;DR
UV is a Rust-powered Python package manager that is 10–100x faster than pip
Install with curl -LsSf https://astral.sh/uv/install.sh | sh
Initialize projects with uv init and add dependencies with uv add package
Run scripts with uv run script.py—no manual virtual environment activation needed
UV replaces pip, virtualenv, pyenv, and pip-tools in a single tool
Lock files (uv.lock) ensure reproducible environments across machines
Use uvx to run CLI tools like black and ruff without permanent installation
The Difference Among UV, Poetry, PIP, Conda, and virtualenv
The first question developers often ask before switching to a new tool is "How does it compare to the one I am already using?". In the Python dependency and project management arena, these four tools are already the most common:
Let's compare UV with each of these tools to help you decide if UV is the right choice for your needs before diving into the details.
UV vs. PIP and virtualenv
PIP and virtualenv have been the traditional tools for Python package management and virtual environment creation. While they get the job done, UV offers several compelling advantages:
Speed: UV's Rust implementation makes it significantly faster than PIP for package installation and dependency resolution, often completing tasks in seconds that would take PIP minutes.
Integrated environment management: While virtualenv handles only environment creation and PIP only handles package management, UV combines both functionalities in a single tool, streamlining the workflow.
UV maintains full compatibility with PIP's ecosystem while addressing its key limitations. It can use the same requirements.txt files and package indexes, making migration seamless. The key differences are:
Performance: UV's parallel downloads and optimized dependency resolver make it 10-100x faster than PIP for large projects.
Memory usage: UV uses significantly less memory than PIP during package installation and dependency resolution.
Error handling: UV provides clearer error messages and better conflict resolution when dependencies clash.
Reproducibility: UV's lockfile approach ensures consistent environments across different systems, something not guaranteed with basic requirements.txt files.
While PIP and virtualenv remain viable options, UV's modern architecture and combined functionality make it an attractive alternative for developers seeking better performance and a more streamlined workflow. The ability to drop UV into existing projects without disrupting established processes makes it particularly appealing for teams looking to gradually modernize their Python development toolchain.
UV vs. Conda
People who don't use PIP and virtualenv usually turn to Conda and they have good reasons:
Conda provides a complete package management solution that handles not just Python packages but also system-level dependencies
It excels at managing complex scientific computing environments with packages like NumPy, SciPy, and TensorFlow
Conda environments are more isolated and reproducible across different operating systems
It has built-in support for different Python versions and can switch between them easily
The Anaconda distribution comes with many pre-installed scientific packages, making it convenient for data scientists
But even hardcore Conda users should consider switching to UV for a variety of reasons. (For a broader comparison of environment management tools, see Anaconda vs Python: Exploring Their Differences.) UV's lightning-fast package installation and dependency resolution can dramatically speed up environment setup compared to Conda's sometimes sluggish performance. Its minimal resource footprint means less memory usage and quicker startups. UV also integrates seamlessly with existing Python packaging standards and tools, making it easier to work with the broader Python ecosystem. For projects that don't require Conda's non-Python package management, UV provides a more streamlined, efficient solution that can significantly improve development workflows.
UV vs. Poetry
I was a Conda user for almost three years but after trying out Poetry a couple of times, I never touched turtle-speed Conda again. Just when I was getting comfortable with Poetry, I came across UV and it offers nearly the same capabilities as Poetry:
Dependency management: Both tools handle package dependencies and virtual environments effectively
Project structure: Both provide tools for initializing and structuring Python projects
Lock files: Both generate lock files to ensure reproducible environments
Package publishing: Both support publishing packages to PyPI
Modern tooling: Both represent modern approaches to Python project management
However, the defining feature of UV is its blazing-fast speed and minimal resource usage. While Poetry is a significant improvement over traditional tools, UV takes performance to another level because of its Rust implementation. Also, UV's compatibility with existing Python packaging means it can work alongside other tools like pip, offering flexibility that Poetry's more opinionated approach sometimes lacks.
Here is a table summarizing the differences we've just covered:
Feature
UV
PIP + virtualenv
Conda
Poetry
Implementation
Rust
Python
Python
Python
Speed
10-100x faster than pip
Baseline
Slower than pip
Faster than pip
Memory Usage
Very efficient
Higher
High
Moderate
Environment Management
Built-in
Separate tools needed
Built-in
Built-in
Dependency Resolution
Fast, modern resolver
Basic
Comprehensive
Modern resolver
Non-Python Packages
No
No
Yes
No
Lock Files
Yes
No (basic requirements.txt)
Yes
Yes
Project Structure
Yes
No
No
Yes
Package Publishing
Yes
Yes (with twine)
Yes
Yes
Compatibility
Works with existing pip ecosystem
Standard Python tool
Own ecosystem
More opinionated approach
Error Handling
Clear error messages
Basic
Good
Good
Resource Footprint
Minimal
Moderate
Heavy
Moderate
Scientific Computing Focus
No
No
Yes
No
Cross-platform Consistency
Yes
Limited
Excellent
Good
If you think UV is worth switching, then read on.
Getting Started With UV For Python Projects
In this section, we cover how to start a project from scratch using UV. If you need help setting up your Python development environment first, check out our dedicated guide. We will discuss how to migrate from existing projects to UV in a later section.
Installing UV
UV can be installed system-wide using cURL on macOS and Linux:
$ curl-LsSf https://astral.sh/uv/install.sh |shPowered by
And with Powershell on Windows (make sure you run Powershell with administrator privileges):
Git is automatically initialized and main git-related files like .gitignore and an empty README.md are generated. .python-version file contains the Python version used for the project, while pyproject.toml serves as the main configuration file for project metadata and dependencies. A sample hello.py file is also created to help you get started quickly.
The first time you run the add command, UV creates a new virtual environment in the current working directory and installs the specified dependencies. On subsequent runs, UV will reuse the existing virtual environment and only install or update the newly requested packages, ensuring efficient dependency management.
Another important process that happens for every add command is resolving dependencies. UV uses a modern dependency resolver that analyzes the entire dependency graph to find a compatible set of package versions that satisfy all requirements. This helps prevent version conflicts and ensures reproducible environments. The resolver considers factors like version constraints, Python version compatibility, and platform-specific requirements to determine the optimal set of packages to install.
UV also updates the pyproject.toml and uv.lock files after each add command. Here is what the TOML file looks like after installing Scikit-learn and XGBoost:
$ cat pyproject.toml
[project]
name ="explore-uv"
version ="0.1.0"
description ="Add your description here"
readme ="README.md"
requires-python =">=3.9"
dependencies =["scikit-learn>=1.5.2",
"xgboost>=2.0.3",
]
To remove a dependency from the environment and the pyproject.toml file, you can use the uv remove command. It will uninstall the package and all its child-dependencies:
We will discuss dependency management in more detail in a later section.
Running Python scripts with UV
Once you install the necessary dependencies, you can start working on your Python scripts as usual. If you are using VS Code, check out our guide on setting up VS Code for Python. UV provides a few different ways to run Python code:
To run a Python script directly, you can use the uv run command followed by your script name instead of the usual python script.py syntax:
The run command ensures that the script is executed inside the virtual environment UV created for the project.
Running scripts with inline dependencies (PEP 723)
UV supports PEP 723 inline script metadata, which lets you declare dependencies directly inside a Python script. This is useful for standalone scripts that need packages without setting up a full project:
Run the script with uv run, and UV automatically creates an isolated environment with the declared dependencies:
$ uv run script.py
GitHub API status: 200Powered by
This is particularly powerful for sharing reproducible scripts with colleagues—anyone with UV installed can run the script without manually installing dependencies.
Managing Python Versions in UV
Managing Python versions is a key part of dependency management. UV provides simple commands to control which Python version you use. Let's explore how to use the uv python command.
Installing Python versions with UV
UV can install and manage Python versions directly, replacing the need for tools like pyenv:
$ uv python install3.12
$ uv python install3.113.13# Install multiple versions at oncePowered by
Python installations are stored in ~/.local/share/uv/python/ and do not interfere with your system Python. You can also pin a project to a specific Python version:
This updates the .python-version file in your project directory. UV will then use this version for all project operations.
Listing existing Python versions
Since it is common for systems to have Python already installed, UV can discover these existing installations by default. For example, to list all the Python versions UV detects on your system, run the following command:
The command correctly detected my Conda and Brew-installed Python versions.
Changing Python versions for the current project
You can switch Python versions for your current UV project at any point as long as the new version satisfies the specifications in your pyproject.toml file. For example, the following file requires Python versions 3.9 and above:
This means you can change the Python version in .python-version file to any version above, like 3.11.7. Afterwards, call uv sync.
The command first checks against existing Python installations. If the requested version isn't found, UV downloads and installs it inside the /Users/username/.local/share/uv/python path. UV also creates a new virtual environment inside the project directory, replacing the old one.
The uv sync command handles everything automatically—it creates the new virtual environment and reinstalls all dependencies from your pyproject.toml and uv.lock files. No additional installation step is needed.
Note that sometimes uv commands may raise Permission Denied errors. In those cases, be sure to use the sudo command if you are on macOS or Linux or run your command prompt with administrator privileges if you are on Windows. Even better solution would be to change the ownership of the UV home directory to the user:
$ sudochown-R$USER ~/.local/share/uv # macOS or Linux
Some Python packages are exposed as command-line tools like black for code formatting, flake8 for linting, pytest for testing, mypy for type checking, etc. UV provides two special interfaces to manage these packages:
When these commands are run, UV creates a temporary virtual environment in its cache. The requested tool is installed and run from there. In other words, you can use command-line tools without installing them in the project's virtual environment, resulting in faster execution and cleaner project dependencies.
Key points about the tool run interfaces:
Works with any Python package that provides command-line tools like flake8, mypy, black or pytest
Cached environments are automatically cleaned up when clearing UV's cache
New cached environments are created on-demand when needed
Perfect for occasional use of development tools
For tools you use frequently, install them permanently with uv tool install:
$ uv tool install ruff
$ uv tool install black
$ ruff check .# Now available directly in PATHPowered by
Permanently installed tools are available globally via your PATH, without polluting any project's virtual environment. You can update them with uv tool upgrade ruff and list all installed tools with uv tool list.
Lock files (uv.lock) are an essential part of dependency management in UV. When you run uv add commands to install dependencies, UV automatically generates and updates a uv.lock file. This lock file serves several critical purposes:
It records the exact versions of all dependencies and their sub-dependencies that were installed.
It ensures reproducible builds by "locking" dependency versions across different environments.
It helps prevent "dependency hell" by maintaining consistent package versions.
It speeds up installations since UV can use the locked versions instead of resolving dependencies again.
UV manages the lock file automatically - you don't need to manually edit it. The lock file should be committed to version control to ensure all developers use the same dependency versions.
The Difference Between Lock Files and requirements.txt
While both lock files and requirements.txt serve to track dependencies, they have distinct purposes and use cases. Lock files contain detailed information about exact package versions and their complete dependency tree, ensuring consistent environments across development. Requirements.txt files are simpler, typically listing only direct dependencies, and are widely supported across Python tools.
Lock files are essential for development to maintain reproducible builds and prevent dependency conflicts. Requirements.txt files are better suited for deployment scenarios or when sharing code with users who may not use UV. They're also necessary for compatibility with tools and services that don't support UV's lock file format.
You can maintain both files by using UV's lock file for development while generating a requirements.txt for deployment. To generate a requirements.txt from a UV lock file, use the following command:
This creates the text file with pinned versions based on your lock file, making it easy to share your project's dependencies in a standard format while still benefiting from UV's advanced dependency management during development.
In this section, we will explore more sophisticated methods to manage dependencies in UV. We will learn how to update dependencies, make them optional, or make them part of a dependency group.
Updating dependencies
In long-term projects, it is common to update the packages you are using to bring the most up-to-date features to the table. Or sometimes, a package you are using introduces breaking changes and you want to ensure that version doesn't get installed accidentally in your environment. The add command can be used again in these and any other scenario where you need to change the constraints or versions of existing dependencies.
Optional dependencies are packages that are not required for the core functionality of your project but may be needed for specific features. For example, Pandas has an excel extra and a plot extra to avoid the installation of Excel parsers and matplotlib unless someone explicitly requires them. Optionals are usually installed with the pip install pandas[plot, excel] syntax.
With UV, this syntax is slightly different. First, ensure that the core Pandas package is installed:
Once they are resolved, they will be listed in your pyproject.toml with the following format:
[project]
name = "explore-uv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.9"
dependencies = ["pandas[plot,excel]>=2.2.3","requests>=2.32.3",]Powered by
Dependency groups
Dependency groups allow you to organize your dependencies into logical groups, such as development dependencies, test dependencies, or documentation dependencies. This is useful for keeping your production dependencies separate from your development dependencies.
To add a dependency to a specific group, use the --group flag:
Then, users will be able to control which groups to install using the --group, --only-group, and --no-group tags.
Switching From PIP and Virtualenv to UV
Migrating from PIP and virtualenv to UV is straightforward since UV maintains compatibility with existing Python packaging standards. Here's a step-by-step guide to make the transition smooth:
1. Converting an existing virtualenv project
If you have an existing project using virtualenv and pip, start by generating a requirements.txt file from your current environment if you haven't already:
Here's a quick reference for replacing common pip and virtualenv commands with their UV equivalents:
pip/virtualenv command
UV equivalent
python -m venv .venv
uv venv
pip install package
uv add package
pip install -r requirements.txt
uv pip install -r requirements.txt
pip uninstall package
uv remove package
pip freeze
uv pip freeze
pip list
uv pip list
After migration, you can safely remove your old virtualenv directory and start using UV's virtual environment management. The transition is typically seamless, and you can always fall back to pip commands through UV's pip compatibility layer if needed.
Using UV in CI/CD and Docker
UV's speed makes it particularly valuable in CI/CD pipelines where installing dependencies happens on every build. Here is an example GitHub Actions workflow using UV:
jobs:test:runs-on: ubuntu-latest
steps:-uses: actions/checkout@v4
-name: Install uv
uses: astral-sh/setup-uv@v3
-name: Set up Python
run: uv python install 3.12
-name: Install dependencies
run: uv sync --frozen --dev
-name: Run tests
run: uv run pytest tests/Powered by
The --frozen flag ensures the CI uses exactly the versions in your lock file, failing if the lock file is out of date. This guarantees reproducible builds.
Docker integration
UV can also speed up Docker image builds significantly:
By copying the dependency files first and installing before copying source code, you take full advantage of Docker layer caching. Dependency installation only re-runs when pyproject.toml or uv.lock changes.
Conclusion
UV represents a significant advancement in Python package management, offering a modern, fast, and efficient alternative to traditional tools. Its key advantages include:
Blazing fast performance with 10-100x speed improvements over pip
Seamless integration with existing Python packaging standards
Built-in virtual environment management
Efficient dependency resolution and lock file support
Low memory footprint and resource usage
Whether you're starting a new project or migrating an existing one, UV provides a robust solution that can significantly improve your Python development workflow. Its compatibility with existing tools makes it an easy choice for developers looking to modernize their toolchain without disrupting their current processes.
As the Python ecosystem continues to evolve, tools like UV demonstrate how modern technologies like Rust can enhance the development experience while maintaining the simplicity and accessibility that Python developers value.
If you like to learn more about dependency management or Python in general, refer to these additional sources:
Is UV faster than pip for Python package management?⌄
Yes, UV is significantly faster than pip, offering 10-100x speed improvements for package installation and dependency resolution. This performance boost is achieved through UV's Rust implementation and optimized parallel download capabilities. For large projects especially, tasks that take minutes with pip can be completed in seconds with UV.
Can I use UV with existing pip requirements.txt files?⌄
Yes, UV is fully compatible with existing pip requirements.txt files and can directly import them using the command uv pip install -r requirements.txt. UV maintains compatibility with the Python packaging ecosystem while providing better performance and dependency management features.
What are the advantages of UV over Poetry and Conda?⌄
UV offers several advantages over both Poetry and Conda:
Faster performance due to Rust implementation
Lower memory usage and resource footprint
Better compatibility with existing Python tooling
Simpler workflow compared to Conda
More flexible approach compared to Poetry's opinionated structure
While Conda excels at managing non-Python packages and Poetry offers robust project management, UV provides the best balance of speed and compatibility.
Does UV support virtual environments?⌄
Yes, UV includes built-in virtual environment management. When you run uv add for the first time in a project, it automatically creates a virtual environment and manages it for you. UV combines environment creation and package management in a single tool, streamlining the Python development workflow compared to using separate tools like pip and virtualenv.
Bex Tuychiev builds voice agents and LLM systems, and most of his work goes into making them reliable enough to run in production, preferably in healthcare.
Looking to expand your data science stack in 2022? This guide highlights 10 of the fastest-growing Python packages that solve various problems you might encounter.
This article teaches you about numerical optimization, highlighting different techniques. It discusses Python packages such as SciPy, CVXPY, and Pyomo and provides a practical DataLab notebook to run code examples.
What is Python UV?
UV is a modern, high-performance Python package manager and installer written in Rust. It serves as a drop-in replacement for traditional Python package management tools like
pip, offering significant improvements in speed, reliability, and dependency resolution.This tool represents a new generation of Python package managers, designed to address common pain points in the Python ecosystem such as slow installation times, dependency conflicts, and environment management complexity. UV achieves this through its innovative architecture and efficient implementation, making it 10-100 times faster than traditional package managers.
Key features that make UV stand out:
Whether working on small personal projects or managing large-scale Python applications, UV provides a robust and efficient solution for package management. In this tutorial, we will cover all essential aspects of UV so you can start using it immediately.
TL;DR
curl -LsSf https://astral.sh/uv/install.sh | shuv initand add dependencies withuv add packageuv run script.py—no manual virtual environment activation neededuv.lock) ensure reproducible environments across machinesuvxto run CLI tools likeblackandruffwithout permanent installationThe Difference Among UV, Poetry, PIP, Conda, and virtualenv
The first question developers often ask before switching to a new tool is "How does it compare to the one I am already using?". In the Python dependency and project management arena, these four tools are already the most common:
Let's compare UV with each of these tools to help you decide if UV is the right choice for your needs before diving into the details.
UV vs. PIP and
virtualenvPIP and
virtualenvhave been the traditional tools for Python package management and virtual environment creation. While they get the job done, UV offers several compelling advantages:virtualenvhandles only environment creation and PIP only handles package management, UV combines both functionalities in a single tool, streamlining the workflow.UV maintains full compatibility with PIP's ecosystem while addressing its key limitations. It can use the same
requirements.txtfiles and package indexes, making migration seamless. The key differences are:requirements.txtfiles.While PIP and virtualenv remain viable options, UV's modern architecture and combined functionality make it an attractive alternative for developers seeking better performance and a more streamlined workflow. The ability to drop UV into existing projects without disrupting established processes makes it particularly appealing for teams looking to gradually modernize their Python development toolchain.
UV vs. Conda
People who don't use PIP and
virtualenvusually turn to Conda and they have good reasons:But even hardcore Conda users should consider switching to UV for a variety of reasons. (For a broader comparison of environment management tools, see Anaconda vs Python: Exploring Their Differences.) UV's lightning-fast package installation and dependency resolution can dramatically speed up environment setup compared to Conda's sometimes sluggish performance. Its minimal resource footprint means less memory usage and quicker startups. UV also integrates seamlessly with existing Python packaging standards and tools, making it easier to work with the broader Python ecosystem. For projects that don't require Conda's non-Python package management, UV provides a more streamlined, efficient solution that can significantly improve development workflows.
UV vs. Poetry
I was a Conda user for almost three years but after trying out Poetry a couple of times, I never touched turtle-speed Conda again. Just when I was getting comfortable with Poetry, I came across UV and it offers nearly the same capabilities as Poetry:
However, the defining feature of UV is its blazing-fast speed and minimal resource usage. While Poetry is a significant improvement over traditional tools, UV takes performance to another level because of its Rust implementation. Also, UV's compatibility with existing Python packaging means it can work alongside other tools like
pip, offering flexibility that Poetry's more opinionated approach sometimes lacks.Here is a table summarizing the differences we've just covered:
Feature
UV
PIP + virtualenv
Conda
Poetry
Implementation
Rust
Python
Python
Python
Speed
10-100x faster than pip
Baseline
Slower than pip
Faster than pip
Memory Usage
Very efficient
Higher
High
Moderate
Environment Management
Built-in
Separate tools needed
Built-in
Built-in
Dependency Resolution
Fast, modern resolver
Basic
Comprehensive
Modern resolver
Non-Python Packages
No
No
Yes
No
Lock Files
Yes
No (basic requirements.txt)
Yes
Yes
Project Structure
Yes
No
No
Yes
Package Publishing
Yes
Yes (with twine)
Yes
Yes
Compatibility
Works with existing pip ecosystem
Standard Python tool
Own ecosystem
More opinionated approach
Error Handling
Clear error messages
Basic
Good
Good
Resource Footprint
Minimal
Moderate
Heavy
Moderate
Scientific Computing Focus
No
No
Yes
No
Cross-platform Consistency
Yes
Limited
Excellent
Good
If you think UV is worth switching, then read on.
Getting Started With UV For Python Projects
In this section, we cover how to start a project from scratch using UV. If you need help setting up your Python development environment first, check out our dedicated guide. We will discuss how to migrate from existing projects to UV in a later section.
Installing UV
UV can be installed system-wide using cURL on macOS and Linux:
And with Powershell on Windows (make sure you run Powershell with administrator privileges):
UV is available via Homebrew as well:
A PIP install is supported but it is not recommended:
Afterward, you can verify the installation by running
uv version:Updating UV
UV can update itself when installed via the standalone installer:
If you installed UV via Homebrew, use
brew upgrade uvinstead. You can also enable shell autocompletion for UV commands:Initializing a new project
Working on projects is the core part of the UV experience. You start by initializing an empty project using the
uv initcommand:The command will immediately create a new
explore-uvdirectory with the following contents:Git is automatically initialized and main git-related files like
.gitignoreand an emptyREADME.mdare generated..python-versionfile contains the Python version used for the project, whilepyproject.tomlserves as the main configuration file for project metadata and dependencies. A samplehello.pyfile is also created to help you get started quickly.You can learn more about creating projects from the UV documentation.
Adding initial dependencies to the project
UV combines the environment creation and dependency installation into a single command -
uv add:The first time you run the
addcommand, UV creates a new virtual environment in the current working directory and installs the specified dependencies. On subsequent runs, UV will reuse the existing virtual environment and only install or update the newly requested packages, ensuring efficient dependency management.Another important process that happens for every
addcommand is resolving dependencies. UV uses a modern dependency resolver that analyzes the entire dependency graph to find a compatible set of package versions that satisfy all requirements. This helps prevent version conflicts and ensures reproducible environments. The resolver considers factors like version constraints, Python version compatibility, and platform-specific requirements to determine the optimal set of packages to install.UV also updates the
pyproject.tomlanduv.lockfiles after each add command. Here is what the TOML file looks like after installing Scikit-learn and XGBoost:To remove a dependency from the environment and the
pyproject.tomlfile, you can use theuv removecommand. It will uninstall the package and all its child-dependencies:We will discuss dependency management in more detail in a later section.
Running Python scripts with UV
Once you install the necessary dependencies, you can start working on your Python scripts as usual. If you are using VS Code, check out our guide on setting up VS Code for Python. UV provides a few different ways to run Python code:
To run a Python script directly, you can use the
uv runcommand followed by your script name instead of the usualpython script.pysyntax:The
runcommand ensures that the script is executed inside the virtual environment UV created for the project.Running scripts with inline dependencies (PEP 723)
UV supports PEP 723 inline script metadata, which lets you declare dependencies directly inside a Python script. This is useful for standalone scripts that need packages without setting up a full project:
Run the script with
uv run, and UV automatically creates an isolated environment with the declared dependencies:This is particularly powerful for sharing reproducible scripts with colleagues—anyone with UV installed can run the script without manually installing dependencies.
Managing Python Versions in UV
Managing Python versions is a key part of dependency management. UV provides simple commands to control which Python version you use. Let's explore how to use the
uv pythoncommand.Installing Python versions with UV
UV can install and manage Python versions directly, replacing the need for tools like
pyenv:Python installations are stored in
~/.local/share/uv/python/and do not interfere with your system Python. You can also pin a project to a specific Python version:This updates the
.python-versionfile in your project directory. UV will then use this version for all project operations.Listing existing Python versions
Since it is common for systems to have Python already installed, UV can discover these existing installations by default. For example, to list all the Python versions UV detects on your system, run the following command:
The command correctly detected my Conda and Brew-installed Python versions.
Changing Python versions for the current project
You can switch Python versions for your current UV project at any point as long as the new version satisfies the specifications in your
pyproject.tomlfile. For example, the following file requires Python versions 3.9 and above:This means you can change the Python version in
.python-versionfile to any version above, like 3.11.7. Afterwards, calluv sync.The command first checks against existing Python installations. If the requested version isn't found, UV downloads and installs it inside the
/Users/username/.local/share/uv/pythonpath. UV also creates a new virtual environment inside the project directory, replacing the old one.The
uv synccommand handles everything automatically—it creates the new virtual environment and reinstalls all dependencies from yourpyproject.tomlanduv.lockfiles. No additional installation step is needed.Note that sometimes
uvcommands may raisePermission Deniederrors. In those cases, be sure to use thesudocommand if you are on macOS or Linux or run your command prompt with administrator privileges if you are on Windows. Even better solution would be to change the ownership of the UV home directory to the user:To learn more about managing Python versions with UV, refer to the documentation.
What Are UV Tools And How to Use Them?
Some Python packages are exposed as command-line tools like
blackfor code formatting,flake8for linting,pytestfor testing,mypyfor type checking, etc. UV provides two special interfaces to manage these packages:1. Using
uv tool run:2. Using the shorter and more convenient
uvxcommand:When these commands are run, UV creates a temporary virtual environment in its cache. The requested tool is installed and run from there. In other words, you can use command-line tools without installing them in the project's virtual environment, resulting in faster execution and cleaner project dependencies.
Key points about the tool run interfaces:
uv tool install:Permanently installed tools are available globally via your
PATH, without polluting any project's virtual environment. You can update them withuv tool upgrade ruffand list all installed tools withuv tool list.Read the UV Tools section of the documentation to learn more about these interfaces.
What Are Lock Files in UV?
Lock files (
uv.lock) are an essential part of dependency management in UV. When you runuv addcommands to install dependencies, UV automatically generates and updates auv.lockfile. This lock file serves several critical purposes:UV manages the lock file automatically - you don't need to manually edit it. The lock file should be committed to version control to ensure all developers use the same dependency versions.
The Difference Between Lock Files and
requirements.txtWhile both lock files and
requirements.txtserve to track dependencies, they have distinct purposes and use cases. Lock files contain detailed information about exact package versions and their complete dependency tree, ensuring consistent environments across development. Requirements.txt files are simpler, typically listing only direct dependencies, and are widely supported across Python tools.Lock files are essential for development to maintain reproducible builds and prevent dependency conflicts. Requirements.txt files are better suited for deployment scenarios or when sharing code with users who may not use UV. They're also necessary for compatibility with tools and services that don't support UV's lock file format.
You can maintain both files by using UV's lock file for development while generating a
requirements.txtfor deployment. To generate arequirements.txtfrom a UV lock file, use the following command:This creates the text file with pinned versions based on your lock file, making it easy to share your project's dependencies in a standard format while still benefiting from UV's advanced dependency management during development.
You can learn more about managing lock files from the documentation.
Advanced Dependency Management With UV
In this section, we will explore more sophisticated methods to manage dependencies in UV. We will learn how to update dependencies, make them optional, or make them part of a dependency group.
Updating dependencies
In long-term projects, it is common to update the packages you are using to bring the most up-to-date features to the table. Or sometimes, a package you are using introduces breaking changes and you want to ensure that version doesn't get installed accidentally in your environment. The
addcommand can be used again in these and any other scenario where you need to change the constraints or versions of existing dependencies.1. Installing the latest version of a package:
2. Installing a specific version:
3. Change the bounds of a package's constraints:
4. Make a dependency platform-specific:
Adding optional dependencies
Optional dependencies are packages that are not required for the core functionality of your project but may be needed for specific features. For example, Pandas has an
excelextra and aplotextra to avoid the installation of Excel parsers and matplotlib unless someone explicitly requires them. Optionals are usually installed with thepip install pandas[plot, excel]syntax.With UV, this syntax is slightly different. First, ensure that the core Pandas package is installed:
Then, install it with its optional extras using square bracket notation:
Once they are resolved, they will be listed in your
pyproject.tomlwith the following format:Dependency groups
Dependency groups allow you to organize your dependencies into logical groups, such as development dependencies, test dependencies, or documentation dependencies. This is useful for keeping your production dependencies separate from your development dependencies.
To add a dependency to a specific group, use the
--groupflag:Then, users will be able to control which groups to install using the
--group,--only-group, and--no-grouptags.Switching From PIP and Virtualenv to UV
Migrating from PIP and virtualenv to UV is straightforward since UV maintains compatibility with existing Python packaging standards. Here's a step-by-step guide to make the transition smooth:
1. Converting an existing virtualenv project
If you have an existing project using
virtualenvand pip, start by generating arequirements.txtfile from your current environment if you haven't already:Then, create a new UV project in the same directory:
Finally, install the dependencies from your requirements file:
2. Replacing common pip/virtualenv commands
Here's a quick reference for replacing common pip and virtualenv commands with their UV equivalents:
pip/virtualenv command
UV equivalent
python -m venv .venvuv venvpip install packageuv add packagepip install -r requirements.txtuv pip install -r requirements.txtpip uninstall packageuv remove packagepip freezeuv pip freezepip listuv pip listAfter migration, you can safely remove your old virtualenv directory and start using UV's virtual environment management. The transition is typically seamless, and you can always fall back to
pipcommands through UV'spipcompatibility layer if needed.Using UV in CI/CD and Docker
UV's speed makes it particularly valuable in CI/CD pipelines where installing dependencies happens on every build. Here is an example GitHub Actions workflow using UV:
The
--frozenflag ensures the CI uses exactly the versions in your lock file, failing if the lock file is out of date. This guarantees reproducible builds.Docker integration
UV can also speed up Docker image builds significantly:
By copying the dependency files first and installing before copying source code, you take full advantage of Docker layer caching. Dependency installation only re-runs when
pyproject.tomloruv.lockchanges.Conclusion
UV represents a significant advancement in Python package management, offering a modern, fast, and efficient alternative to traditional tools. Its key advantages include:
Whether you're starting a new project or migrating an existing one, UV provides a robust solution that can significantly improve your Python development workflow. Its compatibility with existing tools makes it an easy choice for developers looking to modernize their toolchain without disrupting their current processes.
As the Python ecosystem continues to evolve, tools like UV demonstrate how modern technologies like Rust can enhance the development experience while maintaining the simplicity and accessibility that Python developers value.
If you like to learn more about dependency management or Python in general, refer to these additional sources: