Claude Code for Python projects benefits more from a well-tuned CLAUDE.md than from any other configuration step. Python’s fragmented packaging landscape, its import conventions, and the gap between a Python-aware AI agent and a generic one all live or die on what you put in your project memory. This guide covers the CLAUDE.md patterns, slash commands, virtual environment handling, testing integration, and language-specific gotchas that turn Claude Code from a generic coding assistant into a Python specialist that knows your project’s conventions without being told every session.

Claude Code Python: What You’ll Learn
This is a practical claude code python guide for engineers who want to use Claude Code effectively against Django, FastAPI, Flask, data science notebooks, or any other Python workload. You will see two complete CLAUDE.md templates, slash command patterns for common Python workflows, the right way to teach Claude Code about your virtual environment, pytest integration that actually works, and the language-specific gotchas that cause most of the “Claude Code wrote code that didn’t fit my project” complaints. If you want a deeper grounding in Claude Code fundamentals first, the Getting Started with Claude Code guide is the right starting point.
We will also address the gaps. Python’s dynamic typing, multi-version matrix, and slow startup all create friction points that more statically-typed languages avoid. Claude Code can absolutely work around these, but only if you tell it about your specific project’s quirks. The CLAUDE.md patterns below are how you do that.
Why Python Projects Need Extra Configuration
Claude Code is a generalist agent, but its defaults are tuned for the median project across all languages. For Python, those defaults often miss the mark because Python has more per-project variation than most languages. A modern Python project might use uv, poetry, pip-tools, pip directly, hatch, pdm, or any combination of these, and the conventions differ enough that a generic “install dependencies” instruction is ambiguous.
Python also has multi-version runtime support concerns. A repo might target Python 3.10, 3.11, 3.12, and 3.13 simultaneously, with conditional dependencies per version. Claude Code has no way to know which version is the project’s primary target unless you tell it. This affects syntax suggestions (the walrus operator is 3.8+, match statements are 3.10+, type statement aliases are 3.12+), standard library availability (tomllib is 3.11+), and third-party library compatibility.
Python’s testing ecosystem is similarly fragmented. pytest is dominant but unittest is still common, and the right test-discovery command depends on your project structure. Some projects use pytest-xdist for parallel tests, others use pytest-asyncio for async work, and each plugin adds its own CLI flags. Claude Code will guess “pytest” by default, which is usually but not always right.
Finally, Python projects often have implicit conventions that are not documented anywhere: which linter is authoritative (ruff? black? both?), whether type hints are required, the maximum complexity threshold, the import ordering style. A well-tuned CLAUDE.md captures these as explicit rules so Claude Code’s suggestions match your project’s existing style rather than fighting it.
The Web Application CLAUDE.md Template
For a typical Django or FastAPI web application, the CLAUDE.md below captures the conventions that matter most. Adapt the specific tooling choices to your project, but keep the structure: environment, commands, conventions, and constraints.
# Project: Web Application
## Environment
- Python: 3.12 (managed via pyenv)
- Package manager: uv (https://github.com/astral-sh/uv)
- Virtual environment: .venv at project root
- Activate before running any command: `source .venv/bin/activate`
## Commands
- Install dependencies: `uv sync` (do NOT use `pip install`)
- Add a dependency: `uv add <package>`
- Add a dev dependency: `uv add --dev <package>`
- Run the dev server: `uv run uvicorn app.main:app --reload --port 8000`
- Run tests: `uv run pytest --maxfail=1 --disable-warnings -q`
- Run a single test: `uv run pytest tests/test_foo.py::test_bar -v`
- Type check: `uv run mypy src/`
- Lint: `uv run ruff check .`
- Format: `uv run ruff format .`
## Conventions
- ALWAYS activate the venv before running Python commands
- Use type hints everywhere; new code without hints is a bug
- Prefer Pydantic models for API request/response schemas
- Database access goes through SQLAlchemy 2.0 ORM, no raw SQL
- Async endpoints preferred; use `async def` unless blocking IO is unavoidable
- Errors raised as domain-specific exceptions, caught in middleware, returned as RFC 7807 Problem Details
## Constraints
- NEVER use `requests` for HTTP; use `httpx` (async by default)
- NEVER import from `tests/` in production code
- NEVER use `print()` for logging; use the `structlog` logger
- NEVER commit changes that fail `ruff check` or `mypy`
- Database migrations are managed by Alembic; never edit schema files directly
Notice the use of ALL CAPS for non-negotiable rules. Claude Code weights uppercase imperatives more heavily than lowercase prose, which makes the constraints section more enforceable. The Constraints section is the single most important block: it prevents the agent from suggesting patterns you have explicitly rejected.
The Commands section is also critical. Listing the exact commands for common tasks means Claude Code does not need to guess whether to use pip install or uv add, and the agent will run your project’s actual commands rather than the generic defaults. Always include the activate-virtual-environment step explicitly, because Claude Code’s default shell does not auto-activate virtual environments.
The Data Science CLAUDE.md Template
Data science projects have different conventions. Notebooks live alongside source code, exploratory work tolerates more imperfection, and the testing story is usually weaker. The template below adapts to that reality.
# Project: Data Analysis Pipeline
## Environment
- Python: 3.11
- Package manager: pip via requirements.txt (pinned)
- Virtual environment: venv at project root
- Jupyter: via `jupyter lab`
## Commands
- Install dependencies: `pip install -r requirements.txt`
- Update a dependency: edit requirements.txt, then reinstall
- Run notebook server: `jupyter lab`
- Run data pipeline: `python -m src.pipeline --config configs/prod.yaml`
- Run tests: `pytest tests/ -v` (test coverage is partial; do not fail pipelines on missing tests)
## Conventions
- Notebooks are for exploration; productionizable code goes in src/
- Use pandas for tabular data, polars for >5GB datasets
- Visualizations via plotly (interactive) or matplotlib (static reports)
- All file paths via pathlib, never raw string concatenation
- Random seeds set explicitly at the top of any notebook or script
## Constraints
- NEVER upload raw data to the repo; data lives in /data/ (gitignored)
- NEVER commit notebook outputs (use nbstripout pre-commit hook)
- NEVER hardcode credentials; use python-dotenv to load .env
- Functions in src/ must have docstrings (Google style)
- Reproducibility matters: log library versions in any generated report
The data science template is more permissive about testing because the field is. Demanding full pytest coverage on a notebook-heavy project fights the workflow. Instead, the focus is on reproducibility (pinned requirements, explicit seeds) and security (no raw data, no hardcoded credentials).
Teaching Claude Code About Virtual Environments
The single most common Python-specific failure is Claude Code running commands against the wrong Python environment. The default Claude Code shell inherits whatever environment was active when Claude Code was started, which is usually not the project’s virtual environment. The result is pip install against system Python, pytest picking up the wrong package versions, and confusing import errors that an agent has no good way to recover from.
There are three solutions, in increasing order of robustness. The first is to document the activation step in CLAUDE.md, as both templates above do. Claude Code reads CLAUDE.md at session start and will prepend the activation to subsequent commands. This works for explicit commands but can fail for ad-hoc commands the agent constructs.
The second solution is to start Claude Code from inside an already-activated virtual environment. If your shell prompt shows (.venv) when you start Claude Code, the agent inherits that environment and every command it runs also has the venv active. This is the most reliable pattern for developer workstations.
The third solution, for projects that use uv, is to use uv run for every command. uv run pytest automatically resolves the project’s virtual environment and runs the command inside it, without requiring explicit activation. The CLAUDE.md template above uses this pattern. It is the most robust option because it does not depend on shell state at all.
# Start Claude Code inside the activated venv
cd ~/projects/myapp
source .venv/bin/activate
claude
# OR: use uv run everywhere (no activation needed)
cd ~/projects/myapp
claude
# Inside Claude Code:
# > uv run pytest tests/test_foo.py -v
For Django projects specifically, mention manage.py in your CLAUDE.md so Claude Code knows to use it rather than the bare django-admin. The command python manage.py makemigrations is project-specific in a way django-admin is not, and the agent needs to know which to use.
Slash Commands for Python Workflows
Claude Code supports custom slash commands via markdown files in .claude/commands/. Each file becomes a slash command available in the session. For Python projects, a small set of commands covers most of the repetitive work.
# .claude/commands/test.md
Run the relevant tests for the work just done:
1. Identify which files were modified in this session
2. Run pytest for those files specifically, with -v and --tb=short
3. If any tests fail, fix the issue and re-run
4. Report final test results
# .claude/commands/lint.md
Run the project's full quality gate:
1. `uv run ruff format .` (auto-format)
2. `uv run ruff check . --fix` (lint with auto-fix)
3. `uv run mypy src/` (type check)
4. Report any remaining issues
# .claude/commands/migrate.md
Create and apply a Django migration for the changes in this session:
1. Identify model changes that need a migration
2. Run `python manage.py makemigrations`
3. Inspect the generated migration file
4. Run `python manage.py migrate` on a scratch database
5. Report the migration filename for review
The slash commands encode the project’s specific workflow as reusable invocations. Rather than typing out the full test command, the developer types /test and Claude Code runs the right thing. The command file format is plain markdown, so editing them is frictionless.
pytest Integration Patterns
pytest is the dominant Python testing framework, and Claude Code integrates with it well — when configured correctly. The key is teaching the agent about your project’s specific pytest setup rather than assuming defaults.
Most projects use pytest plugins that require specific CLI flags. pytest-asyncio needs --asyncio-mode=auto or decorators on async tests. pytest-xdist adds -n auto for parallel execution. pytest-cov adds --cov=src for coverage. Document the right flag combination in CLAUDE.md, or better, in a pytest.ini or pyproject.toml section that pytest auto-discovers.
# pyproject.toml
[tool.pytest.ini_options]
asyncio_mode = "auto"
addopts = "-ra --strict-markers --tb=short"
testpaths = ["tests"]
filterwarnings = [
"error::DeprecationWarning",
"ignore::PendingDeprecationWarning",
]
With pytest config in pyproject.toml, the bare command pytest produces the right behavior. Claude Code does not need to remember any flags, and the configuration applies identically in CI. This is cleaner than documenting flag combinations in CLAUDE.md.
For test file naming, the convention test_*.py for files and test_* for functions is universal. Make sure Claude Code follows it: new test files should be named tests/test_<module>.py, new test functions test_<behavior>. Class-based tests (class TestFoo:) are an older pattern that some projects still use; document which style your project prefers.
For fixtures, the conftest.py file is pytest’s extension point. Document the fixtures your project relies on so Claude Code knows they exist and uses them rather than reinventing the wheel. A common gotcha is Claude Code writing a setup block when a fixture already provides the same thing.
Django-Specific Patterns
Django projects have their own conventions that benefit from explicit documentation. The manage.py wrapper, the apps-per-domain structure, the ORM, the template system, and the admin all have specific patterns Claude Code should follow.
Document the Django version in CLAUDE.md. Django 4.2 LTS, 5.0, and 5.1 have meaningfully different async support, database backend features, and template tag behavior. Claude Code’s knowledge of Django is broad but benefits from version pinning to avoid suggesting features that don’t exist in your version.
For ORM work, explicitly state whether raw SQL is permitted and under what circumstances. Most Django projects prefer the ORM exclusively, with raw SQL reserved for performance-critical paths where the ORM is too slow. Claude Code defaults to ORM usage, which is correct for most projects, but confirm it explicitly.
For migrations, document whether they should be auto-generated (makemigrations) or hand-written. Most projects use auto-generation with manual review, but some high-discipline projects write migrations by hand to enforce review. Claude Code will auto-generate by default; tell it explicitly if your project is the latter.
For the Django admin, document whether new models should be registered by default. Some projects register every model for quick admin access; others keep the admin minimal and require explicit registration. Both are valid; pick one and document it.
FastAPI-Specific Patterns
FastAPI projects benefit from a CLAUDE.md that documents the API’s structure, dependency injection patterns, and async conventions. FastAPI’s type hints are first-class — they generate OpenAPI schemas, drive validation, and document the API — so type hint completeness is more important than in a typical Python project.
## Conventions
- All endpoints use type hints for both request and response models
- Response models are Pydantic v2, named `<Action>Response` (e.g., `CreateUserResponse`)
- Dependency injection via FastAPI's `Depends()`, never global state
- Async database access via SQLAlchemy 2.0 async sessions
- Background tasks via FastAPI's `BackgroundTasks`, not Celery, for short fire-and-forget work
- Long-running work via Celery with Redis broker
- OpenAPI tags used for endpoint grouping; every endpoint has a tag
FastAPI’s auto-generated OpenAPI schema means your type hints become your API documentation. Claude Code should be told this explicitly so it does not skip type hints on “internal” endpoints that turn out to be customer-facing in the docs. The convention “all endpoints have full type hints” is enforceable via CLAUDE.md.
Async Python Patterns
Modern Python codebases increasingly use async patterns, and the conventions around async are subtle enough to deserve their own section in CLAUDE.md. The fundamental rule is consistency: pick async or sync for each layer and apply it uniformly. Mixing async endpoints with sync database calls (or vice versa) creates the worst of both worlds — slow under load and hard to reason about.
For FastAPI, the convention is async throughout: async endpoints, async database via SQLAlchemy 2.0 async, async HTTP via httpx. The exception is CPU-bound work, which should be pushed to a worker (Celery, RQ, or a thread pool via asyncio.to_thread). Claude Code should be told explicitly when blocking calls are acceptable and when they must be offloaded.
## Async Conventions
- All HTTP endpoints are `async def`
- Database access via async SQLAlchemy sessions (`AsyncSession`)
- External HTTP calls via `httpx.AsyncClient`, never `requests`
- CPU-bound work (image processing, ML inference) goes to Celery workers
- Use `asyncio.gather` for concurrent IO; do not chain awaits sequentially when parallel is safe
A common bug pattern is forgetting await on a coroutine, which produces a “coroutine was never awaited” warning rather than a clear error. Claude Code is good about catching this, but documenting the convention explicitly reduces occurrences. Likewise, mixing sync and async SQLAlchemy sessions in the same project produces confusing errors; pick one and document it.
For Django, the async story is more nuanced. Django added async views in 4.1, async ORM in 4.2 LTS, and async middleware in 5.0. The migration is ongoing, and many third-party Django packages still have sync-only code paths. Document your Django version’s async support explicitly so Claude Code does not suggest async patterns to a version that does not support them.
Dependency Management Deep Dive
Python dependency management has fragmented into several competing tools, each with its own conventions. The choice matters because it affects what Claude Code does when asked to “add a dependency” or “lock the environment.” Documenting the choice in CLAUDE.md prevents the agent from guessing wrong.
uv is the modern default for new projects. It is a Rust-based package manager that is 10-100x faster than pip, handles virtual environment creation, supports lockfiles (uv.lock), and integrates with the standard pyproject.toml format. The uv sync command reproduces the environment from the lockfile, and uv add <package> adds a dependency while updating the lockfile.
poetry remains a strong choice for projects that adopted it before uv matured. It has a slightly different command surface (poetry add instead of uv add), a TOML-based config, and its own lockfile format. Existing poetry projects should not be migrated to uv without reason; the migration is mechanical but disruptive.
pip with requirements.txt is the lowest-common-denominator option. It works everywhere, has no special tooling, and is the right choice for projects with minimal dependencies or strict procurement constraints that prevent third-party package managers. For these projects, document whether requirements.txt is pinned (with exact versions) or floating (with version ranges).
pip-tools layers a lockfile workflow on top of plain requirements.txt: you maintain requirements.in with unpinned dependencies, run pip-compile to produce a pinned requirements.txt, and pip-sync to apply the pinned environment. This is a middle ground that some enterprise teams prefer because it has fewer moving parts than uv or poetry while still providing reproducibility.
Regardless of tool, document the dependency update workflow. Some teams update dependencies monthly as a deliberate exercise; others update opportunistically when a feature requires a newer version. Claude Code should be told whether to suggest updates proactively or wait for explicit instruction.
Performance Profiling Workflow
Python performance work with Claude Code benefits from explicit profiling commands in CLAUDE.md. The default profiling workflow is: measure, identify the bottleneck, optimize, re-measure. Claude Code can perform each step but needs to know which profiler to use and how to interpret its output.
For CPU profiling, py-spy is the modern default. It produces flame graphs that visualize where time is spent, supports profiling production processes without code changes, and has low overhead. cProfile is built into the standard library and is the right choice for ad-hoc profiling where installing py-spy is not possible.
# Profile a script
uv run py-spy record -o profile.svg -- python -m src.pipeline
# Profile a running process
py-spy record -o profile.svg --pid 12345
# Quick line-by-line timing
uv run python -m cProfile -o profile.out -m src.pipeline
uv run snakeviz profile.out
For memory profiling, memray is the modern choice. It tracks allocations across native and Python code, produces flame graphs and heap views, and is essential for tracking down memory leaks in long-running services. Document it in CLAUDE.md if memory profiling is part of your team’s workflow.
Claude Code’s role in profiling is to suggest where to look based on the profile output. Paste the top of a flame graph or the hottest function from cProfile output, and the agent will suggest specific optimizations: algorithmic improvements, caching opportunities, vectorization with NumPy, or offloading to a compiled extension. The agent’s suggestions are most useful when paired with explicit constraints: “we cannot change the public API” or “the data size can grow 10x.”
Debugging and Error Patterns
Python error messages are informative but Claude Code benefits from knowing your project’s debugging conventions. For interactive debugging, pdb is built-in; ipdb and pudb are popular enhanced alternatives. Document which your team uses so Claude Code can suggest the right breakpoint command (breakpoint() works for all of them in Python 3.7+).
For production debugging, structured logging via structlog or logging with JSON formatters is the norm. The log format matters because Claude Code can help parse and analyze logs when they have consistent structure. Document your log format and fields explicitly.
For exception handling, the modern convention is domain-specific exception classes that inherit from a project-wide base exception, with FastAPI exception handlers (or Django middleware) that translate them to HTTP responses. Claude Code should be told to use the project’s exception hierarchy rather than raising generic ValueError or RuntimeError.
Data Science Tooling Conventions
Data science Python projects have a different tool stack from web applications, and Claude Code’s defaults are tuned for the web. Documenting the data-science-specific stack prevents the agent from suggesting pandas where polars is the choice, or matplotlib where plotly is the convention.
The DataFrame library choice is the first decision. pandas is the legacy default with the broadest ecosystem support, but polars is significantly faster for datasets above a few GB and has a cleaner API for lazy evaluation. Many modern data teams use both: pandas for small interactive work, polars for production pipelines. Document the threshold clearly: “Datasets under 1 GB use pandas; above 1 GB use polars.”
The ML framework choice depends on the workload. scikit-learn for classical ML, pytorch for deep learning research, tensorflow for production models at some organizations, xgboost for gradient-boosted trees on tabular data. Claude Code has reasonable defaults but should follow the project’s existing choice rather than introducing a new framework.
For experiment tracking, mlflow is the de facto standard. weights-and-biases is the commercial alternative with better UI. Document which is used so Claude Code logs experiments to the right system rather than just printing metrics to stdout.
For data validation, pandera adds schema validation to DataFrames and is increasingly popular for production pipelines where input data quality matters. pydantic is the right choice for validating API inputs and structured configs. Both have roles in a modern data stack.
Reproducibility is the dominant concern in data science projects. Document library versions explicitly via pinned requirements, set random seeds at the top of every notebook and script, and log environment metadata (Python version, library versions, git SHA) alongside any generated report. Claude Code can automate this metadata capture, but only if told it is required.
Testing Layers and Conventions
Python testing is more than pytest. A mature project has three testing layers with different conventions, and Claude Code should know which layer a new test belongs to. Documenting the layers prevents the agent from writing an integration test where a unit test would do, or vice versa.
Unit tests live in tests/unit/ and test individual functions in isolation. They should not touch the database, the filesystem, or the network. Mock external dependencies via unittest.mock.patch or the responses library. Unit tests should run in milliseconds — if they take longer, they are probably integration tests in disguise.
Integration tests live in tests/integration/ and test multiple components together. They typically involve a real database (often in a Docker container via testcontainers), real HTTP calls to a test server, and real filesystem operations. Integration tests should run in seconds, not milliseconds, and should be separable from unit tests so developers can run just the fast tests during development.
End-to-end tests live in tests/e2e/ and test the whole application as a black box. For web services, they typically use httpx or requests against a running server, often driven by Playwright for browser-driven flows. E2E tests are slow (often minutes per test) and brittle, so they should be focused on critical user journeys rather than comprehensive coverage.
Document the layer conventions in CLAUDE.md so Claude Code places new tests in the right directory and uses the right fixtures. A common mistake is the agent writing a unit test that imports the database session fixture, immediately coupling it to the database. Explicit conventions prevent this.
A Worked Example: Refactoring a Legacy Flask App
Imagine a team inheriting a 50,000-line Flask application that uses Python 3.8, raw SQL via SQLAlchemy 1.4, no type hints, and a tests directory with 12% coverage. They want to use Claude Code to modernize the codebase incrementally over six months without a big-bang rewrite.
The team starts by writing a CLAUDE.md that documents the current state honestly: Python 3.8, no type hints yet, tests are sparse and brittle, the migration target is Python 3.12 with full type hints and 80% coverage. The constraints section is explicit: “Do not add type hints to functions you are not actively modifying. We are doing incremental modernization, not a sweep.”
They configure slash commands for the repetitive modernization tasks: /add-types to add type hints to a specific file, /modernize-sql to convert raw SQL to SQLAlchemy 2.0 patterns, /bump-python to update syntax after a version bump. Each command produces a focused diff that a human reviews before merging.
The first month is spent on test coverage. Claude Code reads each module, writes tests for the documented behavior, and the team reviews the tests to confirm they capture the actual intent. Coverage rises from 12% to 45% over the month, with the new tests catching three latent bugs along the way.
The second month tackles Python version bumps. They move from 3.8 to 3.10 first (relatively safe), test, fix the handful of deprecation warnings, then move to 3.12. Claude Code helps with the syntax modernization: match statements where they improve readability, type aliases where they clarify complex generics, walrus operator where it tightens loops.
The third through sixth months tackle the SQLAlchemy 1.4 to 2.0 migration. This is the riskiest change because the ORM versions have different session semantics. Claude Code helps module by module: convert the query, run the tests, fix the failures, commit. The CLAUDE.md documents which modules are done and which remain.
The end state after six months is a Python 3.12 codebase with 78% test coverage, full type hints on the modified paths, SQLAlchemy 2.0 throughout, and a CLAUDE.md that documents the conventions going forward. None of this required a big-bang rewrite; it was incremental work guided by a well-configured Claude Code.
Claude Code Python: Common Mistakes to Avoid
Python-specific Claude Code failures are predictable. These six mistakes cover most of the regret we see from teams that struggled with adoption.
- Not documenting the package manager: A project that uses
uvbut has Claude Code defaulting topip installends up with conflicting dependency state. Always state the package manager explicitly in CLAUDE.md. - Skipping virtual environment activation: Claude Code inherits the shell state. If you start it outside the venv, every Python command runs against system Python and produces confusing import errors. Activate first, or use
uv run. - Mixing linting tools: A project with both ruff and black configured produces conflicting formatting. Pick one (ruff covers both linting and formatting now) and document it as authoritative.
- Ignoring Python version: Claude Code defaults to recent Python features. If your project targets 3.9 or earlier, the agent will suggest syntax that doesn’t parse. State the target version explicitly.
- Over-constraining the agent: A CLAUDE.md with 50 constraints becomes noise. Focus on the 5-10 non-negotiable rules that genuinely affect correctness; leave stylistic preferences for the linter to enforce.
- Forgetting notebook conventions: Data science projects without
nbstripoutcommit notebook outputs, bloating diffs and leaking state. Document the pre-commit hook setup explicitly.
Claude Code Python: Best Practices
- Write a project-specific CLAUDE.md that documents the Python version, package manager, virtual environment activation, and the canonical commands for install/test/lint/migrate. Generic defaults miss Python-specific variation.
- Prefer
uvoverpipfor new projects.uv run <cmd>handles virtual environment activation transparently, eliminating the most common Python-specific Claude Code failure. - Document your test framework and any plugins (
pytest-asyncio,pytest-xdist) in CLAUDE.md or inpyproject.toml‘s[tool.pytest.ini_options]section so pytest auto-discovers them. - Pin Python version and document language features that are allowed or forbidden. The
matchstatement (3.10+),typealiases (3.12+), and walrus operator (3.8+) all have version dependencies Claude Code needs to know about. - Use slash commands (
.claude/commands/) for repetitive workflows: running tests for modified files, lint-fixing, generating migrations. Each command saves typing and enforces consistency. - Pick one linter/formatter and stick with it. Ruff now covers both linting and formatting; it is the right default for new projects. Document it as authoritative to prevent Claude Code from suggesting alternatives.
- For Django projects, document whether migrations are auto-generated or hand-written, whether raw SQL is permitted, and whether new models register in the admin by default. These conventions vary per project.
- For data science projects, document the notebook vs source code split, the seed-setting policy, and the data-file location. Reproducibility is the dominant concern; explicit rules beat ad-hoc decisions.
Claude Code Python: Frequently Asked Questions
Does Claude Code activate my virtual environment automatically?
No. Claude Code inherits the shell environment from which it was started. Either activate the venv before launching Claude Code, use uv run for every command, or document the activation step explicitly in CLAUDE.md.
Should I use uv, poetry, or pip for new Python projects?
For new projects in 2026, uv is the recommended default. It is dramatically faster than pip and poetry, handles virtual environment activation via uv run, and supports modern packaging standards. Poetry remains viable for existing projects already using it.
How do I stop Claude Code from using deprecated Python syntax?
Document the target Python version in CLAUDE.md and use a linter (ruff) with the appropriate target version configured. Ruff will flag deprecated syntax, and Claude Code will respect the documented version when suggesting new code.
Can Claude Code work with Jupyter notebooks?
Yes. Claude Code reads and writes notebook files directly. Document your notebook conventions in CLAUDE.md: where notebooks live, whether outputs are committed, and the seed-setting policy. Use nbstripout as a pre-commit hook to keep diffs clean.
Does Claude Code support Django and FastAPI equally?
Yes. Both frameworks are well-represented in Claude Code’s training. The difference is project-specific configuration: Django projects need migration and admin conventions documented; FastAPI projects need response model and dependency injection conventions. A tailored CLAUDE.md makes both frameworks productive.
Claude Code for Python projects pays off most when the project’s CLAUDE.md captures the conventions that distinguish it from a generic Python codebase. Document the Python version, package manager (prefer uv), virtual environment activation step, canonical commands, and the 5-10 non-negotiable constraints. Add slash commands for repetitive workflows like test-running and migration generation. The result is an agent that knows your project’s quirks without being reminded every session, which is the difference between Claude Code as a generic assistant and Claude Code as a Python specialist.
Continue Learning
- Getting Started with Claude Code
- CLAUDE.md and Project Memory Guide
- Claude Code VS Code: Easy IDE Guide
For official documentation, see the Claude Code memory guide, the uv documentation, and the pytest documentation. Always verify current tool behavior against your specific Python version.