Python Project Management
Modern Python project setup and dependency management with uv.
Before Writing Code
- •Read
references/pythonic-style.mdfor style conventions - •Check Python version:
pyproject.toml→.python-version→.claude/python-version - •If unknown, ask user once and store in
.claude/python-version
Reference Files
| Topic | When to Load | File |
|---|---|---|
| Pythonic style, conventions | Before generating code | ../references/pythonic-style.md |
| Version-specific features | When adapting to Python version | ../references/version-features.md |
| GitHub Actions, Docker, monorepo | CI/CD and advanced workflows | references/ci-cd-workflows.md |
| Full pyproject.toml templates | Complete configuration examples | references/pyproject-templates.md |
Quick Start
bash
# New project uv init my-project && cd my-project uv python pin 3.12 uv add fastapi pydantic uv add --dev pytest ruff mypy # Existing project uv sync # Install from pyproject.toml uv sync --all-extras # Include optional deps
Project Structure
Source Layout (Recommended)
code
my-package/ ├── pyproject.toml ├── README.md ├── src/ │ └── my_package/ │ ├── __init__.py │ ├── core.py │ └── py.typed ├── tests/ │ └── test_core.py └── .python-version
Why src/ layout: The src/ layout prevents accidental imports from the source tree during
testing. Without it, import my_package might resolve to the local directory instead of the
installed package, masking missing __init__.py files or build configuration errors.
Minimal pyproject.toml
toml
[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "my-package" version = "1.0.0" requires-python = ">=3.10" dependencies = ["requests>=2.28"] [project.optional-dependencies] dev = ["pytest>=7.0", "ruff>=0.1", "mypy>=1.0"] [tool.setuptools.packages.find] where = ["src"] [tool.ruff] line-length = 100 target-version = "py310" [tool.ruff.lint] select = ["E", "F", "I", "UP"]
Dependency Management
Adding Packages
bash
uv add requests # Add to dependencies uv add "django>=4.0,<5.0" # With version constraint uv add --dev pytest ruff # Development dependencies uv add --optional docs sphinx # Optional group uv add -e ./local-package # Editable local
Updating Packages
bash
uv add --upgrade requests # Upgrade specific uv sync --upgrade # Upgrade all uv tree --outdated # Show outdatable
Locking
bash
uv lock # Generate uv.lock uv lock --upgrade # Regenerate with latest uv sync --frozen # Install exact versions (CI)
Python Version Management
bash
uv python install 3.12 # Install Python uv python pin 3.12 # Create .python-version uv python list # List installed
Running Code
bash
uv run python app.py # Run script uv run pytest # Run tests uv run ruff check . # Run linter uv run --python 3.11 script.py # Specific version
CLI Entry Points
With Click
python
# src/my_package/cli.py
import click
@click.group()
@click.version_option()
def cli():
"""My CLI tool."""
@cli.command()
@click.argument("name")
def greet(name: str):
click.echo(f"Hello, {name}!")
def main():
cli()
toml
# pyproject.toml [project.scripts] my-tool = "my_package.cli:main"
bash
uv sync && uv run my-tool greet World
Building and Publishing
bash
# Build uv build # Creates dist/*.whl and dist/*.tar.gz # Test on TestPyPI first uv publish --repository testpypi # Publish to PyPI uv publish
API Token Setup
ini
# ~/.pypirc [pypi] username = __token__ password = pypi-...your-token...
Publishing Checklist
Before publishing:
- • Tests passing (
uv run pytest) - • Version updated in pyproject.toml
- • CHANGELOG updated
- • Build succeeds (
uv build) - • Install works in clean venv
- • Tested on TestPyPI first
Common Issues
bash
# Wrong Python version uv python pin 3.12 && uv venv --python 3.12 # Dependency conflict uv lock --verbose # Cache issues uv cache clean # Lockfile out of sync uv lock --upgrade
Workflow Integration
| Task | Skill |
|---|---|
| Writing tests | python:python-testing |
| Profiling, async | python:python-performance |
| Before claiming done | core:verification |
Best Practices
- •Use
src/layout for libraries - •Pin Python version with
.python-version - •Commit
uv.lockfor reproducibility - •Use
uv runinstead of manual activation - •Test installation in clean venv before publishing
- •Use TestPyPI before real PyPI
- •Automate publishing with GitHub Actions
- •Keep dependencies minimal
- •Use optional groups for dev/docs deps
- •Run
uv sync --frozenin CI