#!/usr/bin/env python3
"""
Basic UV Demo Script
Run with: uv run basic_example.py
"""
def main():
print("Welcome to UV Tutorial!")
print("Hello from UV - Ultra Fast Python Package Manager!")
# Show Python version and location
import sys
print(f"\nPython Version: {sys.version}")
print(f"Python Executable: {sys.executable}")
print(f"Platform: {sys.platform}")
# Show some basic info
import os
print(f"\nCurrent working directory: {os.getcwd()}")
print("\n✅ UV is working perfectly!")
print("Now let's explore more advanced features!")
if __name__ == "__main__":
main()
UV: The Ultra-Fast Python Package Manager
A Comprehensive Beginner’s Guide to Modern Python Development
Introduction
Welcome to the world of UV - the ultra-fast Python package manager that’s revolutionizing how we work with Python projects! If you’ve ever been frustrated by slow pip installations, complex virtual environment setups, or dependency conflicts, UV is here to solve all those problems.
What is UV?
UV is a modern, extremely fast Python package and project manager written in Rust. It’s designed to replace multiple tools you might currently use:
- pip (package installation)
- pip-tools (dependency management)
- pipx (tool installation)
- poetry (project management)
- pyenv (Python version management)
- virtualenv (virtual environments)
Why Choose UV?
- ⚡ Lightning Fast: 10-100x faster than pip
- 🔧 All-in-One: Replaces multiple tools
- 🔒 Reliable: Advanced dependency resolution
- 🐍 Python Management: Built-in Python version handling
- 📦 Modern: Lock files for reproducible builds
- 🌐 Cross-Platform: Works on Windows, macOS, and Linux
Installation
Installing UV
The installation process is straightforward and works across all major platforms.
For macOS and Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
For Windows (PowerShell):
-ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" powershell
Post-Installation Setup
After installation, you need to refresh your terminal environment:
Option 1: Restart your terminal (Recommended)
Option 2: Reload your shell configuration:
source $HOME/.local/bin/env
Verify Installation
Check if UV is installed correctly:
uv --version
You should see output similar to:
uv 0.4.18 (Rust 1.81.0)
Python Version Management
One of UV’s most powerful features is its ability to manage Python versions without needing additional tools like pyenv.
List Available Python Versions
uv python list
This command shows: - Python versions already installed on your system - Python versions available for download
Example output:
* python3.13 -> /usr/bin/python3.13 (system)
* python3.12 -> /usr/bin/python3.12 (system)
python3.11 -> download
python3.10 -> download
Install Specific Python Versions
# Install Python 3.13
uv python install 3.13
# Install Python 3.12
uv python install 3.12
# Install Python 3.11
uv python install 3.11
UV handles the download and installation automatically!
Check Python Version Availability
uv python find 3.13
This returns the path to Python 3.13 if available, or indicates it can be downloaded.
Basic Script Execution
Let’s start with a simple example to see UV in action.
Your First UV Script
Create a file called basic_example.py
:
Run the Script
# Run with default Python
uv run basic_example.py
# Run with specific Python version
uv run --python 3.13 basic_example.py
Temporary Dependencies
Here’s where UV shines! You can run scripts with dependencies without installing them permanently:
# Run a script that needs the 'rich' library
uv run --with rich script_name.py
# Multiple temporary dependencies
uv run --with rich --with requests --python 3.13 script_name.py
Let’s create a more exciting example:
#!/usr/bin/env python3
"""
Rich Library Demo
Run with: uv run --with rich rich_demo.py
"""
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.text import Text
from rich.progress import track
import time
def main():
= Console()
console
# Welcome message
= Text("🚀 UV Package Manager Demo", style="bold blue")
welcome_text = Panel(welcome_text, title="Python Tutorial", border_style="green")
panel print(panel)
console.
# Create a comparison table
print("\n[bold yellow]Package Manager Comparison:[/bold yellow]")
console.
= Table(title="pip vs UV Comparison")
table "Feature", style="cyan", no_wrap=True)
table.add_column("pip", style="red")
table.add_column("UV", style="green")
table.add_column(
= [
comparisons "Installation Speed", "🐌 Slow (10-60s)", "⚡ Lightning Fast (<2s)"),
("Dependency Resolution", "❌ Basic", "✅ Advanced SAT solver"),
("Virtual Environment", "❌ Manual setup", "✅ Automatic"),
("Lock Files", "❌ No lock files", "✅ uv.lock for reproducibility"),
("Python Version Mgmt", "❌ Needs pyenv", "✅ Built-in"),
("Parallel Downloads", "❌ Sequential", "✅ Parallel processing"),
("Caching", "❌ Limited", "✅ Smart global cache")
(
]
# Add rows with animation
for feature, pip_val, uv_val in track(comparisons, description="Loading comparison..."):
table.add_row(feature, pip_val, uv_val)0.3)
time.sleep(
print(table)
console.
# Summary
print("\n[bold green]🎉 UV makes Python development 10x easier and faster![/bold green]")
console.print("[italic]This rich formatting was installed temporarily with --with flag![/italic]")
console.
if __name__ == "__main__":
main()
Run this with:
uv run --with rich rich_demo.py
Project Management
Creating a New Project
UV makes it incredibly easy to start new Python projects:
# Create a new directory and initialize a UV project
mkdir my_awesome_project && cd my_awesome_project
uv init
This creates: - pyproject.toml
- Project configuration file - src/
- Source code directory structure - main.py
- A starter Python file - Virtual environment management (automatic)
Project Structure
After running uv init
, you’ll see:
my_awesome_project/
├── pyproject.toml
├── README.md
├── src/
│ └── my_awesome_project/
│ ├── __init__.py
│ └── py.typed
└── main.py
Script-Based Projects
For simple scripts, you can create a script-based project:
uv init --script main.py --python 3.13
This creates a minimal configuration for single-script projects.
Dependency Management
Adding Dependencies
Adding packages to your project is straightforward:
# Add regular dependencies
uv add requests
uv add beautifulsoup4
uv add rich
# Add with version constraints
uv add "django>=4.0,<5.0"
uv add "requests>=2.25.0"
Development Dependencies
Separate your development tools from production dependencies:
# Add development dependencies
uv add --dev pytest
uv add --dev black
uv add --dev mypy
uv add --dev ruff
Optional Dependencies
Create optional dependency groups for different use cases:
# Add optional dependencies
uv add --optional web fastapi uvicorn
uv add --optional data pandas numpy matplotlib
# Install with optional groups
uv sync --extra web
uv sync --extra data
uv sync --extra web,data
Synchronizing Environment
Keep your environment in sync with your project configuration:
# Install all dependencies
uv sync
# Sync with fresh downloads (ignore cache)
uv sync --refresh
# Show what would be installed (dry run)
uv sync --dry-run
Understanding pyproject.toml
The pyproject.toml
file is the heart of your UV project. It’s written in TOML (Tom’s Obvious Minimal Language), which is designed to be human-readable and easy to parse.
Key sections in pyproject.toml:
[project]
name = "my-awesome-project"
version = "0.1.0"
description = "A sample project using UV"
requires-python = ">=3.8"
dependencies = [
"requests>=2.25.0",
"rich>=10.0.0",
]
[project.optional-dependencies]
dev = [
"pytest>=6.0",
"black>=21.0",
"mypy>=0.800",
]
web = [
"fastapi>=0.68.0",
"uvicorn>=0.15.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.uv]
dev-dependencies = [
"pytest>=6.0",
"black>=21.0",
]
What each section means:
[project]
: Basic project metadata and core dependencies
[project.optional-dependencies]
: Optional groups you can install selectively
[build-system]
: How to build/package your project
[tool.uv]
: UV-specific configuration
Lock Files: Ensuring Reproducibility
UV automatically generates uv.lock
files that contain the exact versions of all dependencies (including transitive dependencies) that work together:
# Update lock file with latest compatible versions
uv lock
# Install exactly what's in the lock file
uv sync --frozen
Why lock files matter:
- Reproducibility: Everyone on your team gets identical environments
- Security: Prevents supply chain attacks through version pinning
- Debugging: Easier to track down issues when versions are consistent
- CI/CD: Ensures production matches development
Lock file example snippet:
[[package]]
name = "requests"
version = "2.31.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "charset-normalizer" },
{ name = "idna" },
{ name = "urllib3" },
]
Synchronization: Keeping Everything in Sync
The uv sync
command is powerful - it ensures your environment exactly matches your project configuration:
# Standard sync - installs missing, updates changed
uv sync
# Sync with specific extras
uv sync --extra dev
uv sync --extra web,dev
# Frozen sync - only installs what's in uv.lock (production mode)
uv sync --frozen
# Refresh sync - ignores cache, downloads fresh
uv sync --refresh
# Dry run - see what would happen without doing it
uv sync --dry-run
What sync does:
- Reads
pyproject.toml
for project requirements - Compares with current environment
- Installs missing packages
- Removes packages not in configuration
- Updates packages to match version constraints
- Creates/updates
uv.lock
if needed
Best practices:
- Run
uv sync
after pulling changes from git - Use
uv sync --frozen
in production/CI - Commit both
pyproject.toml
anduv.lock
to version control
Real-World Example: Student Grade Calculator
Let’s build a practical classroom example - a student grade calculator that reads data from CSV files and generates reports.
Project Setup
mkdir grade_calculator && cd grade_calculator
uv init
uv add pandas rich
Create Sample Data
First, create a sample CSV file students.csv
:
name,math,science,english,history
Alice Johnson,95,88,92,85
Bob Smith,78,91,85,88
Carol Davis,88,95,90,92
David Wilson,92,85,88,90
Eva Brown,85,92,95,88
Frank Miller,90,88,85,92
Grace Lee,88,90,92,85
Henry Clark,92,88,90,88
Ivy Taylor,85,95,88,90
Jack Anderson,90,85,92,88
The Grade Calculator Code
Create grade_calculator.py
:
#!/usr/bin/env python3
"""
Student Grade Calculator - Real world UV example
Dependencies: pandas, rich
Setup commands:
uv init
uv add pandas rich
uv run grade_calculator.py
"""
import pandas as pd
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.progress import track
from rich.text import Text
import statistics
from pathlib import Path
def create_sample_data():
"""Create sample student data if CSV doesn't exist"""
if not Path("students.csv").exists():
= {
data 'name': ['Alice Johnson', 'Bob Smith', 'Carol Davis', 'David Wilson',
'Eva Brown', 'Frank Miller', 'Grace Lee', 'Henry Clark',
'Ivy Taylor', 'Jack Anderson'],
'math': [95, 78, 88, 92, 85, 90, 88, 92, 85, 90],
'science': [88, 91, 95, 85, 92, 88, 90, 88, 95, 85],
'english': [92, 85, 90, 88, 95, 85, 92, 90, 88, 92],
'history': [85, 88, 92, 90, 88, 92, 85, 88, 90, 88]
}= pd.DataFrame(data)
df 'students.csv', index=False)
df.to_csv(return df
return None
#or load the file if you already have it, like below
def load_student_data():
"""Load student data from CSV file"""
try:
= pd.read_csv('students.csv')
df return df
except FileNotFoundError:
= Console()
console print("[red]Error: students.csv not found. Creating sample data...[/red]")
console.return create_sample_data()
def calculate_grades(df):
"""Calculate grades and statistics"""
# Calculate average for each student
= ['math', 'science', 'english', 'history']
subject_columns 'average'] = df[subject_columns].mean(axis=1)
df[
# Assign letter grades
def get_letter_grade(avg):
if avg >= 90: return 'A'
elif avg >= 80: return 'B'
elif avg >= 70: return 'C'
elif avg >= 60: return 'D'
else: return 'F'
'letter_grade'] = df['average'].apply(get_letter_grade)
df[
return df
def display_student_report(df, console):
"""Display individual student grades"""
= Table(
table ="📚 Student Grade Report",
title=True,
show_header="bold blue",
header_style="green"
border_style
)
"Student", style="cyan", width=15)
table.add_column("Math", justify="center", style="yellow")
table.add_column("Science", justify="center", style="yellow")
table.add_column("English", justify="center", style="yellow")
table.add_column("History", justify="center", style="yellow")
table.add_column("Average", justify="center", style="magenta")
table.add_column("Grade", justify="center", style="bold green")
table.add_column(
for _, student in track(df.iterrows(), description="Processing grades...", total=len(df)):
# Color code the letter grade
= {
grade_color 'A': 'bold green',
'B': 'green',
'C': 'yellow',
'D': 'orange1',
'F': 'red'
'letter_grade'], 'white')
}.get(student[
table.add_row('name'],
student[str(int(student['math'])),
str(int(student['science'])),
str(int(student['english'])),
str(int(student['history'])),
f"{student['average']:.1f}",
f"[{grade_color}]{student['letter_grade']}[/{grade_color}]"
)
print(table)
console.
def display_class_statistics(df, console):
"""Display class-wide statistics"""
= ['math', 'science', 'english', 'history']
subject_columns
# Calculate statistics
= Table(
stats_table ="📊 Class Statistics",
title=True,
show_header="bold magenta",
header_style="blue"
border_style
)
"Subject", style="cyan")
stats_table.add_column("Average", justify="center")
stats_table.add_column("Highest", justify="center", style="green")
stats_table.add_column("Lowest", justify="center", style="red")
stats_table.add_column("Std Dev", justify="center")
stats_table.add_column(
for subject in subject_columns:
= df[subject].mean()
avg = df[subject].max()
highest = df[subject].min()
lowest = df[subject].std()
std_dev
stats_table.add_row(
subject.title(),f"{avg:.1f}",
str(int(highest)),
str(int(lowest)),
f"{std_dev:.1f}"
)
print(stats_table)
console.
# Grade distribution
= df['letter_grade'].value_counts().sort_index()
grade_dist
print("\n[bold yellow]📈 Grade Distribution:[/bold yellow]")
console.for grade, count in grade_dist.items():
= (count / len(df)) * 100
percentage print(f" {grade}: {count} students ({percentage:.1f}%)")
console.
def generate_report_file(df):
"""Generate a detailed report file"""
= []
report_content "STUDENT GRADE REPORT")
report_content.append("=" * 50)
report_content.append("")
report_content.append(
for _, student in df.iterrows():
f"Student: {student['name']}")
report_content.append(f" Math: {student['math']}")
report_content.append(f" Science: {student['science']}")
report_content.append(f" English: {student['english']}")
report_content.append(f" History: {student['history']}")
report_content.append(f" Average: {student['average']:.1f}")
report_content.append(f" Letter Grade: {student['letter_grade']}")
report_content.append("")
report_content.append(
# Class statistics
"CLASS STATISTICS")
report_content.append("-" * 30)
report_content.append(= ['math', 'science', 'english', 'history']
subject_columns for subject in subject_columns:
= df[subject].mean()
avg f"{subject.title()} Average: {avg:.1f}")
report_content.append(
f"\nClass Average: {df['average'].mean():.1f}")
report_content.append(
# Save to file
with open('grade_report.txt', 'w') as f:
'\n'.join(report_content))
f.write(
def main():
= Console()
console
# Header
= Panel(
header_panel "[bold blue]🎓 Student Grade Calculator[/bold blue]",
="Powered by UV Package Manager",
subtitle="green"
border_style
)print(header_panel)
console.
# Load data
with console.status("[bold green]Loading student data...", spinner="dots"):
= load_student_data()
df if df is None:
print("[red]Failed to load data![/red]")
console.return
print(f"[green]✅[/green] Loaded data for {len(df)} students")
console.
# Calculate grades
with console.status("[bold blue]Calculating grades...", spinner="bouncingBall"):
= calculate_grades(df)
df
print("[green]✅[/green] Grades calculated successfully!")
console.
# Display results
display_student_report(df, console)print("")
console.
display_class_statistics(df, console)
# Generate report file
generate_report_file(df)print(f"\n[bold green]💾 Detailed report saved to grade_report.txt[/bold green]")
console.
# Summary
= df['average'].mean()
class_avg print(f"\n[bold cyan]📊 Class Average: {class_avg:.1f}[/bold cyan]")
console.
= df.loc[df['average'].idxmax()]
highest_student print(f"[bold green]🏆 Top Student: {highest_student['name']} ({highest_student['average']:.1f})[/bold green]")
console.
print("\n[italic]This calculator demonstrates UV's dependency management![/italic]")
console.print("[dim]Dependencies: pandas, rich[/dim]")
console.
if __name__ == "__main__":
main()
Run the Calculator
uv run grade_calculator.py
This will:
- Load student data from the CSV file (or create sample data if needed)
- Calculate averages and assign letter grades for each student
- Display a beautiful grade report with color-coded grades
- Show class statistics including averages, highest/lowest scores, and standard deviation
- Generate a text report saved to
grade_report.txt
- Display grade distribution showing how many students got each letter grade
Features demonstrated:
- Data processing with pandas
- Beautiful terminal output with rich
- File I/O operations
- Statistical calculations
- Error handling for missing files
- Progress indicators and status updates
Advanced Features
Virtual Environment Management
While UV handles virtual environments automatically, you can also manage them manually:
# Create a virtual environment
uv venv
# Create with specific Python version
uv venv --python 3.13
# Activate virtual environment (if needed)
source .venv/bin/activate # On macOS/Linux
.venv\Scripts\activate # On Windows
External Tools
Run tools from PyPI without permanent installation:
# Run httpie for API testing
uv run --with httpie http GET https://api.github.com/users/octocat
# Run cowsay for fun
uv run --with cowsay cowsay "UV is awesome!"
# Run black for code formatting
uv run --with black black --check .
Import and Export
Work with existing projects and requirements:
# Install from requirements.txt
uv pip install -r requirements.txt
# Export current dependencies
uv export --format requirements-txt --output-file requirements.txt
uv export --format pyproject-toml
Build and Publish
Package and distribute your projects:
# Build distribution packages
uv build
# Publish to PyPI
uv publish
Testing with UV
Setting up Tests
Add testing dependencies:
uv add --dev pytest pytest-cov
Create a simple test file test_example.py
:
def add_numbers(a, b):
return a + b
def multiply_numbers(a, b):
return a * b
def test_add_numbers():
assert add_numbers(2, 3) == 5
assert add_numbers(-1, 1) == 0
assert add_numbers(0, 0) == 0
def test_multiply_numbers():
assert multiply_numbers(2, 3) == 6
assert multiply_numbers(-1, 5) == -5
assert multiply_numbers(0, 10) == 0
Run tests:
# Run all tests
uv run pytest
# Run with verbose output
uv run pytest -v
# Run with coverage
uv run pytest --cov
# Run specific test file
uv run pytest test_example.py
Performance Comparison
Here’s why UV is so much faster than traditional tools:
Operation | pip | UV | Improvement |
---|---|---|---|
Install requests | 12.3s | 0.8s | 15.4x faster |
Install django | 45.2s | 2.1s | 21.5x faster |
Install tensorflow | 180.5s | 8.3s | 21.7x faster |
Create virtual environment | 3.2s | 0.1s | 32x faster |
Dependency resolution | 8.7s | 0.3s | 29x faster |
- Written in Rust: Compiled language with excellent performance
- Parallel Downloads: Downloads multiple packages simultaneously
- Smart Caching: Global cache shared across projects
- Advanced Resolution: Efficient SAT solver for dependencies
- Optimized Algorithms: Modern algorithms for package management
Best Practices
1. Project Organization
- Always use
uv init
for new projects - Keep
pyproject.toml
clean and well-documented
- Commit
uv.lock
to version control - Use meaningful project names and descriptions
2. Dependency Management
- Pin critical dependency versions in
pyproject.toml
- Use
uv sync
regularly to keep environment updated - Separate development and production dependencies
- Use optional dependencies for feature groups
3. Python Version Management
- Specify Python version requirements in
pyproject.toml
- Test your project with multiple Python versions
- Use
uv run --python X.Y
for version-specific testing - Document Python version requirements
4. Team Collaboration
- Always commit
pyproject.toml
anduv.lock
- Document special installation requirements
- Use consistent Python versions across team
- Provide clear setup instructions
5. Performance Tips
- Use
uv cache
to share packages across projects - Pre-install commonly used Python versions
- Use
uv sync --frozen
in production environments - Leverage UV’s parallel processing capabilities
Troubleshooting
Common Issues and Solutions
Issue: “uv: command not found”
# Solution: Restart terminal or reload shell
source ~/.bashrc # or ~/.zshrc
Issue: Python version not found
# Solution: Install the Python version first
uv python install 3.13
Issue: Dependencies not resolving
# Solution: Clear cache and try again
uv cache clean
uv sync --refresh
Issue: Virtual environment issues
# Solution: Recreate virtual environment
rm -rf .venv
uv venv
uv sync
Useful Diagnostic Commands
# Check UV configuration
uv config
# Show project information
uv project info
# Check dependency tree
uv tree
# Validate project
uv check
# Show cache location and size
uv cache dir
uv cache size
# Clean cache
uv cache clean
Migration from Other Tools
From pip to UV
Replace your pip workflows:
# Old way
python -m venv myenv
source myenv/bin/activate
pip install requests beautifulsoup4
# New way
uv init myproject
cd myproject
uv add requests beautifulsoup4
From Poetry to UV
Convert Poetry projects:
- Copy dependencies from
pyproject.toml
[tool.poetry.dependencies] - Run
uv init
in project directory - Add dependencies with
uv add package_name
- Remove Poetry files if desired
From pipenv to UV
Replace Pipfile with UV:
- Extract packages from Pipfile
- Run
uv init
- Add packages with
uv add
- Use
uv run
instead ofpipenv run
Example Workflow
Here’s a complete workflow for a new Python project:
# 1. Create and navigate to project directory
mkdir my_awesome_project && cd my_awesome_project
# 2. Initialize UV project
uv init
# 3. Add your dependencies
uv add requests beautifulsoup4 rich
uv add --dev pytest black mypy ruff
# 4. Install everything
uv sync
# 5. Run your application
uv run main.py
# 6. Run tests
uv run pytest
# 7. Format code
uv run black .
# 8. Type check
uv run mypy .
# 9. Lint code
uv run ruff check .
Conclusion
UV represents the future of Python package management. By combining speed, reliability, and modern features into a single tool, it simplifies Python development workflows dramatically.
Key Takeaways
- Speed: UV is 10-100x faster than traditional tools
- Simplicity: One tool replaces many separate utilities
- Reliability: Advanced dependency resolution prevents conflicts
- Modern: Built-in support for lock files and reproducible builds
- Cross-platform: Consistent experience across operating systems
Next Steps
- Try UV Today: Install UV and experiment with your current projects
- Migrate Gradually: Start with new projects, then migrate existing ones
- Share with Team: Introduce UV to your development team
- Stay Updated: Follow UV development for new features
- Contribute: Report issues and contribute to the UV community
Resources
- Official Documentation: https://docs.astral.sh/uv/
- GitHub Repository: https://github.com/astral-sh/uv
- Community Discord: Join discussions with other UV users
- Migration Guide: Official guides for switching from other tools
Happy coding with UV! 🚀
UV is developed by Astral, the same team behind Ruff (the ultra-fast Python linter). Their focus on performance and developer experience makes UV an excellent choice for modern Python development.
Citation
@online{rasheduzzaman2025,
author = {Md Rasheduzzaman and Rasheduzzaman, Md},
title = {UV: {The} {Ultra-Fast} {Python} {Package} {Manager}},
date = {2025-09-20},
langid = {en}
}