Do1e

Do1e

github
email

Use uv to manage Python environments

This article is synchronized and updated to xLog by Mix Space
For the best browsing experience, it is recommended to visit the original link
https://do1e.cn/posts/citelab/how-to-use-uv


Introduction#

Everyone is promoting how fast uv is (UV: The Python package management tool - 100 times faster than pip), but for our laboratory, which may need to migrate Python environments between multiple machines, the convenience of reproducing environments with uv is also worth noting.

Although I have been trying to recommend uv to my peers, everyone still has a deep reliance on conda and is reluctant to try new tools.
Therefore, I decided to write a tutorial to introduce how to use uv, to slightly promote the transformation of environment management in the laboratory.

Installing uv#

Official Documentation

On Windows, I still recommend using winget for installation:

winget install astral.uv

On Linux/macOS, you can refer to the official documentation to install using curl/wget:

curl -LsSf https://astral.sh/uv/install.sh | sh
# or
wget -qO- https://astral.sh/uv/install.sh | sh

Initializing the uv Environment#

If you need to initialize a new project, you can run the following in your workspace directory:

uv init [project-name]
cd [project-name]

Or if you need to migrate an existing Python project to the uv environment, you can run the following in the project directory:

cd [project-name]
uv init

At this point, the following files will be created in the project directory:

.git
.gitignore
main.py
pyproject.toml
.python-version
README.md
  1. .git, .gitignore, and README.md are self-explanatory.
  2. main.py is a sample Python file and can be deleted if not needed.
  3. pyproject.toml is the configuration file for the Python project that records the project's metadata and dependencies, with content roughly as follows:
    [project]
    name = "test-project"
    version = "0.1.0"
    description = "Add your description here"
    readme = "README.md"
    requires-python = ">=3.12"
    dependencies = []
    
  4. .python-version is used to specify the Python version for the current project.

Specifying the Python Version#

Edit the requires-python field in the pyproject.toml file to specify the required Python version for the current project, such as ==3.12, >=3.12, etc.

Then run the following command to install the specified version of Python:

uv python pin 3.12

Creating a Virtual Environment#

uv venv

This command will create a virtual environment in the current project directory, with the folder named .venv. You can then refer to its output information to activate the virtual environment, such as:

source .venv/bin/activate
# or on Windows
.venv\Scripts\activate

Managing Project Dependencies#

Basic Usage#

When you need to install new dependencies, you can use the following command:

uv add [package-name]

In fact, it simply replaces pip install with uv add, but this command not only installs the dependency into the virtual environment but also automatically writes the dependency information into the dependencies field in the pyproject.toml file and updates the uv.lock lock file to ensure the reproducibility of dependency versions. The uv.lock file should not be edited manually, but it is crucial for environment reproduction, do not put it in .gitignore.

For example, after installing requests, the pyproject.toml will only have an additional requests dependency, while uv.lock will detail the specific version information of requests and all its sub-dependencies. You can view the dependency tree using the uv tree command:

> uv tree
Resolved 6 packages in 0.75ms
test-project v0.1.0
└── requests v2.32.5
    ├── certifi v2025.11.12
    ├── charset-normalizer v3.4.4
    ├── idna v3.11
    └── urllib3 v2.6.1

If you no longer need a certain dependency, you can use the following command to uninstall it:

uv remove [package-name]

Try to strictly use uv commands to manage the environment. Although uv pip command is provided to be compatible with pip usage, this command will not update the pyproject.toml and uv.lock files, which will lead to issues with environment reproducibility.

Mirror Sources#

If you need to change the Pypi mirror source, you can add the following content to the pyproject.toml file (using Nanjing University mirror as an example):

[[tool.uv.index]]
name = "nju-mirror"
url = "https://mirror.nju.edu.cn/pypi/web/simple"
default = true

index-url in pip#

Some packages are published on their own PyPI mirror sources, such as the pip installation command for torch (see torch official documentation) as follows:

pip3 install torch torchvision --index-url https://download.pytorch.org/whl/cu130

You need to refer to Using uv with PyTorch to add the following content to the pyproject.toml file:

[[tool.uv.index]]
name = "pytorch-cu130"
url = "https://download.pytorch.org/whl/cu130"
explicit = true

[tool.uv.sources]
torch = [
  { index = "pytorch-cu130", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]
torchvision = [
  { index = "pytorch-cu130", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]

Otherwise, the CUDA version of torch and torchvision will not be installed, and the CPU version will be installed instead.

Here, we first define an index source named pytorch-cu130, with the url specified as the --index-url given in the above torch documentation, but it is recommended to use the Nanjing University mirror source https://mirror.nju.edu.cn/pytorch/whl/cu130.
Then, in tool.uv.sources, we specify that the packages torch and torchvision need to be installed from this index source (note: the marker specifies that the pytorch-cu130 index is only used when the operating system is Linux or Windows. For other operating systems, such as macOS, this configuration will be ignored and the default source will still be used).

Reproducing the Environment#

When you need to reproduce the current project's Python environment on another machine, simply clone the project code and run the following command:

uv sync

If you want to reproduce the same environment in another project, you can copy the pyproject.toml, uv.lock, and .python-version files to the target project directory, update the project information in pyproject.toml, and then run the same command:

uv sync

Building and Publishing Packages#

If you are writing a PyPI package for others to install, you also need to consider which dependencies are development dependencies and which are runtime dependencies. Development dependencies need to be installed using the uv add --dev [package-name] command.

After that, you also need to supplement the project information in the pyproject.toml file, such as author, license, and build information. Considering that most of the time in scientific research, packages are not published, I will not elaborate here, but you can refer to the following content for understanding:

[project]
name = "NJUlogin"
version = "3.6.1"
description = "The Nanjing University login module, which can be used to login to the various campus web sites"
authors = [{ name = "Do1e", email = "[email protected]" }]
readme = "README.md"
requires-python = ">=3.10,<4.0"
dependencies = [
    "requests>=2.32.0",
    "pillow>=11.0.0",
    "numpy>=2.0.0",
    "lxml>=5.3.0",
    "pycryptodome>=3.21.0",
    "onnxruntime>=1.20.0",
    "cryptography>=43.0.0",
]
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]


[project.scripts]
NJUlogin = "NJUlogin.__main__:main"

[tool.setuptools.packages.find]
include = ["NJUlogin", "NJUlogin.*"]

[project.urls]
Homepage = "https://github.com/Do1e/NJUlogin"
Repository = "https://github.com/Do1e/NJUlogin"

[dependency-groups]
dev = [
    "pre-commit>=4.3.0",
    "ruff>=0.14.6",
]

[[tool.uv.index]]
url = "https://mirror.nju.edu.cn/pypi/web/simple"
publish-url = "https://upload.pypi.org/legacy/"
default = true

[tool.ruff]
line-length = 100

[tool.ruff.lint]
ignore = ["C901", "E501", "E721", "E741", "F402", "F823"]
select = ["C", "E", "F", "I", "W"]

[tool.ruff.lint.isort]
lines-after-imports = 2

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[tool.uv]
package = true

After that, you can use the following commands to build and publish the package:

uv build
uv publish

Other Useful Commands#

  1. uv cache clear: Clear the uv cache to free up disk space.
  2. uv tree: View the dependency tree of the current project.
  3. uv run main.py: Equivalent to activating the virtual environment and running python main.py, can be used to run Python scripts in the project.
  4. uvx [script-name]: Run tools; some Python packages provide command-line tools that can be run using the uvx command, for example, uvx NJUlogin -h.
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.