Python

Python virtual environments with uv: select and verify the interpreter

Create an isolated Python environment with uv, bind package operations to that interpreter and verify isolation before diagnosing import failures.

A virtual environment gives a project its own Python executable and installed packages. With uv, create the environment first, then explicitly direct package installation and execution to that interpreter. This prevents the common mistake of installing into one Python and running another.

This workflow uses the command-line uv tool and Python 3.12. The executable paths below use macOS or Linux conventions. On Windows, the environment's interpreter is .venv\Scripts\python.exe, and activation uses the script for your shell. Activation is optional when every command names the interpreter explicitly.

Create a small reproducible workspace

Run these commands from a new directory. The example pins a small teaching dependency so installation does not float to a different version later. It is not a claim that this is the newest version or a dependency recommendation for every project.

uv venv --python 3.12 .venv
uv pip install --python .venv/bin/python 'packaging==26.3'
.venv/bin/python -c "from packaging.version import Version; print(Version('1.10') > Version('1.9'))"
uv pip check --python .venv/bin/python
uv pip freeze --python .venv/bin/python

The version comparison prints True: 1.10 is greater than 1.9 under package version rules. A string comparison would answer a different question. pip check verifies installed dependency compatibility; it does not prove that your application behaves correctly.

We also ran this workflow in a fresh temporary directory, separate from the article-verification environment. The following Python check can be saved as check_environment.py and executed with .venv/bin/python check_environment.py. It checks the interpreter being used rather than guessing from the terminal prompt.

import sys
from packaging.version import Version

print('isolated interpreter:', sys.prefix != sys.base_prefix)
print('numeric package versions:', Version('1.10') > Version('1.9'))
assert sys.prefix != sys.base_prefix
assert Version('1.10') > Version('1.9')

Checked output:

isolated interpreter: True
numeric package versions: True

Diagnose an import that still fails

First print sys.executable in the program or notebook that raises ModuleNotFoundError. Compare that path with the interpreter supplied to uv pip install --python. If they differ, installing the package again into an unrelated environment will not repair the actual runtime.

An editor may use a cached interpreter selection, and a notebook kernel may belong to another environment entirely. Select the project interpreter in the editor or install and register the appropriate notebook kernel. Restart the kernel after changing its environment. Shell activation changes command lookup for that shell; it does not automatically change an already running notebook process.

A file named packaging.py in the project can also shadow the real package. Check the imported module's __file__ when an import resolves to an unexpected location. That path is diagnostic information, not something to hardcode into application code.

Separate an environment snapshot from a project lock

uv pip freeze records what is installed in this environment. It does not describe why each dependency was selected, and a snapshot on one platform does not guarantee identical behavior on every other platform. Keep the Python version, platform requirements and the program's own checks alongside the dependency record.

For a maintained project, uv's project workflow uses pyproject.toml, uv lock and uv sync --locked. The lockfile records resolution information; commit it with the project and run checks after syncing. Avoid mixing ad hoc installation with a project sync without understanding that syncing can remove undeclared packages.

Make the environment disposable

Keep source files outside .venv, exclude the directory from version control and recreate it from declared dependencies. Do not copy a virtual environment between machines: interpreter paths and compiled wheels can be platform-specific. Recreating a clean environment is also a useful test for accidental reliance on globally installed packages.

The Python course provides the programming foundations. Once the interpreter is reliable, try the beginner projects; for scientific work, the Data Tools course develops the array and table workflows that use additional packages.

References

uv environment guide — Interpreter selection, environment discovery and explicit package installation.

uv project guide — Project metadata, locking and synchronization.

Related course

Learn Python from zero, the way machine learning code uses it: names and objects, types, control flow, data structures, functions, classes, testing and working with an AI assistant.

Open lessons' parts and key terms are free to read, with no account.

What you will be able to do

  • Predict what a piece of Python code does before running it.
  • Read an error message and find the line that caused it.
  • Write functions, classes and tests for real data tasks.
  • Read and check code an AI assistant wrote for you.