0%

Virtual Environment via UV

November 15, 2025

Python

1. uv

1.1. Introduction

UV is a package manager that can replace the virtual environment manager such as conda and pyenv.

1.2. Installation

For mac user we simply execute:

curl -LsSf https://astral.sh/uv/install.sh | sh

We can execute uv --version to check whether uv is installed.

1.3. pyproject.toml and .python-version

1.3.1. uv sync from existing pyproject.toml

With the presence of

  1. pyproject.toml for definition all dependencies and their version
  2. .python-version for definition of python version

we can execute

uv sync

to install all specified dependences. The directory .venv/ will be created to install everything needed to launch a virtual environment.

1.3.2. add specific package

The command

uv add package_name

will automatically update the pyproject.toml and uv.lock for for us (just like package.json and package.lock.json).

1.4. How to Set the name of the Virtual Environment Generated by a uv project

We execute

uv project metadata --set name="agents"

It will set a value in pyproject.toml:

Now we can select agents from the python interpretor or from the kernels of jupyter notebook.

1.5. How to Generatge the good old requirement.txt if we still need it?

The file requirement.txt is not strictly necessary if we are using uv throughoutly. If someone is still using conda or pyenv for virtual environments, then export one for them:

uv pip compile pyproject.toml -o requirements.txt

2. Virtual Environment by uv

2.1. What uv sync does

uv automatically manages a virtual environment:

  • ✅ Creates a .venv directory (or custom location)
  • ✅ Installs all dependencies there
  • ✅ Isolates your project from system Python
  • ✅ You don't manually create it—uv sync does

The command

uv sync

automatically:

  1. Creates or updates .venv/
  2. Installs all dependencies from pyproject.toml
  3. Ready to use

2.2. Execute python Script in uv virtual environment

python something.py is now replaced by

uv run something.py

3. Sync to uv Project via requirements.txt

First uv init and change to correct python version. Then create a file called sync_to_uv.sh and execute it:

#!/bin/bash

# Script to install from requirements.txt and sync to pyproject.toml
# Usage: ./sync_to_uv.sh [requirements.txt]

REQUIREMENTS_FILE="${1:-requirements.txt}"

if [ ! -f "$REQUIREMENTS_FILE" ]; then
    echo "❌ Error: $REQUIREMENTS_FILE not found"
    exit 1
fi

if [ ! -f "pyproject.toml" ]; then
    echo "❌ Error: pyproject.toml not found"
    exit 1
fi

echo "� Step 1: Ensuring virtual environment exists..."
if [ ! -d ".venv" ]; then
    echo "   Creating .venv..."
    uv venv
fi

echo ""
echo "📦 Step 2: Installing packages from $REQUIREMENTS_FILE..."
uv pip install -r "$REQUIREMENTS_FILE"

if [ $? -ne 0 ]; then
    echo "❌ Failed to install packages"
    exit 1
fi

echo ""
echo "🔍 Step 2: Reading installed packages..."

# Get installed packages in format: package==version
INSTALLED=$(uv pip freeze | grep -v "^-e " | sort)

# Format for pyproject.toml
TMP_DEPS=$(mktemp)
echo "$INSTALLED" | sed 's/==/>=/g' | awk '{print "    \"" $0 "\","}' > "$TMP_DEPS"

# Remove trailing comma from last line
sed -i '' '$ s/,$//' "$TMP_DEPS"

echo ""
echo "✏️  Step 4: Updating pyproject.toml..."

# Create temporary output file
TMP_FILE=$(mktemp)

# Read through pyproject.toml and replace dependencies
IN_DEPS=0
while IFS= read -r line; do
    if [[ "$line" =~ ^dependencies[[:space:]]*=[[:space:]]*\[ ]]; then
        # Handle both "dependencies = [" and "dependencies = []"
        echo "dependencies = [" >> "$TMP_FILE"
        cat "$TMP_DEPS" >> "$TMP_FILE"
        echo "]" >> "$TMP_FILE"
        IN_DEPS=1
        # If it's on one line (dependencies = []), skip it entirely
        if [[ "$line" =~ \]$ ]]; then
            IN_DEPS=0
        fi
    elif [[ $IN_DEPS -eq 1 && "$line" =~ ^\] ]]; then
        # Already closed above, skip this line
        IN_DEPS=0
    elif [[ $IN_DEPS -eq 0 ]]; then
        echo "$line" >> "$TMP_FILE"
    fi
    # else: skip lines inside the old dependencies array
done < "pyproject.toml"

# Replace original file
mv "$TMP_FILE" "pyproject.toml"
rm "$TMP_DEPS"

echo "✅ Successfully synced $(echo "$INSTALLED" | wc -l | tr -d ' ') packages to pyproject.toml"
echo ""
echo "📦 Sample dependencies added:"
echo "$INSTALLED" | head -10
TOTAL=$(echo "$INSTALLED" | wc -l | tr -d ' ')
if [ "$TOTAL" -gt 10 ]; then
    echo "   ... and $(expr $TOTAL - 10) more"
fi

echo ""
echo "🔄 Step 5: Running uv sync to update lock file..."
uv sync

if [ $? -eq 0 ]; then
    echo ""
    echo "✅ Complete! Your environment is now synced with pyproject.toml and uv.lock"
else
    echo ""
    echo "⚠️  Warning: uv sync had issues, but pyproject.toml was updated"
fi

This shell script will

  1. Install all the packages into the virtual environment according to the requirements.txt, and then;

  2. Sync back the installed packages into the toml file of the uv project.

  3. Finally it uv sync to update the lock file to version the installed package versions.