How to Convert constraints.txt to uv constraint-dependencies in pyproject.toml
Understanding Constraints in Astral's uv
Astral's uv has taken the Python ecosystem by storm due to its exceptional speed and modern dependency resolution. When migrating legacy projects—especially those managed via standard pip—you often end up with a large constraints.txt file. Constraints define version bounds for packages if they end up being required by your dependencies, without forcing them to be installed directly.
In uv, project-level constraints are defined under the [tool.uv] table inside your pyproject.toml using the constraint-dependencies key:
[tool.uv]
constraint-dependencies = [
"Jinja2==3.1.6",
"requests==2.33.1"
]Currently, uv does not provide a built-in CLI command like uv import constraints.txt to automatically write those constraints into pyproject.toml. However, you have two clean and idiomatic ways to resolve this.
Method 1: Keep using constraints.txt via configuration (Recommended for Large Files)
If your constraints.txt file contains dozens or hundreds of lines, pasting them into pyproject.toml can quickly clutter your configuration file. Instead of converting the file contents into inline TOML strings, you can instruct uv to read your existing constraints.txt directly.
Add the following setting to your pyproject.toml:
[tool.uv]
override-dependencies = []
# Pass constraints directly during resolution
When running commands, you can use the --constraint (or -c) flag:
uv lock --constraint constraints.txt
# or
uv pip sync --constraint constraints.txtAlternatively, set the UV_CONSTRAINT environment variable in your CI/CD pipeline or local environment:
export UV_CONSTRAINT=constraints.txtMethod 2: Convert constraints.txt to pyproject.toml via Python Script
If you prefer to keep everything in a single pyproject.toml file and remove constraints.txt entirely, you can run a simple Python script to parse the requirement specs and update pyproject.toml programmatically.
Using Python 3.11+ (built-in tomllib) and the standard library (or tomli_w for writing TOML):
import path
from pathlib import Path
import tomllib
import tomli_w
# 1. Parse valid lines from constraints.txt
constraints_path = Path("constraints.txt")
constraints = []
if constraints_path.exists():
for line in constraints_path.read_text().splitlines():
line = line.strip()
# Skip comments and empty lines
if line and not line.startswith("#"):
constraints.append(line)
# 2. Read pyproject.toml
pyproject_path = Path("pyproject.toml")
with open(pyproject_path, "rb") as f:
pyproject_data = tomllib.load(f)
# 3. Update [tool.uv] constraint-dependencies
tool_section = pyproject_data.setdefault("tool", {})
uv_section = tool_section.setdefault("uv", {})
uv_section["constraint-dependencies"] = constraints
# 4. Write back to pyproject.toml
with open(pyproject_path, "wb") as f:
tomli_w.dump(pyproject_data, f)
print(f"Successfully imported {len(constraints)} constraints into pyproject.toml!")Note: Install tomli_w via uv pip install tomli-w or uv run --with tomli-w python script.py if you don't already have a TOML writer package installed.
Method 3: Quick One-Liner with Python
If you just want a quick inline command to update your pyproject.toml without extra dependencies, you can use a Python one-liner combined with standard regex formatting if your TOML structure is simple:
python3 -c '
from pathlib import Path
lines = [f" \"{l.strip()}\"," for l in Path("constraints.txt").read_text().splitlines() if l.strip() and not l.startswith("#")]
print("[tool.uv]\nconstraint-dependencies = [\n" + "\n".join(lines) + "\n]")
'Summary
- Is there a native command? Not currently—
uvdoesn't have an automated parser command to populateconstraint-dependenciesdirectly from a file. - Best Practice: For very long constraint files, pass
--constraint constraints.txtor setUV_CONSTRAINT=constraints.txtto keeppyproject.tomlreadable. - For single-file projects: Use the Python script with
tomli_wto cleanly migrate your entries intopyproject.toml.