A project-based SciPy setup keeps the scientific Python stack tied to one directory instead of a manually activated environment. uv creates the project metadata, resolves SciPy and NumPy, and runs Python through the managed project environment when a calculation should be reproducible from the project files.
The SciPy install page recommends project-based workflows such as uv for new users. In this workflow, pyproject.toml records the direct dependency, uv.lock records the resolved dependency set, and .venv holds the local environment that uv manages for the project.
A terminal with uv already installed is enough to start. The smoke check uses scipy.integrate after installation because a successful import alone does not prove that SciPy numerical modules are running inside the project environment.
$ uv init scipy-demo Initialized project `scipy-demo` at `/home/user/scipy-demo`
Replace scipy-demo with the directory name for the project.
$ cd scipy-demo
$ uv add scipy Using CPython 3.13.14 interpreter at: /usr/local/bin/python3.13 Creating virtual environment at: .venv Resolved 3 packages in 252ms ##### snipped ##### Installed 2 packages in 35ms + numpy==2.5.0 + scipy==1.18.0
uv add writes the dependency to pyproject.toml, updates uv.lock, and syncs .venv for the project. Exact package versions and timing change as new wheels are released.
import scipy from scipy import integrate value, error = integrate.quad(lambda x: x**2, 0, 1) print(f"SciPy {scipy.__version__}") print(f"integral={value:.6f}") print(f"estimated_error={error:.2e}")
$ uv run python main.py SciPy 1.18.0 integral=0.333333 estimated_error=3.70e-15
The integral of x^2 from 0 to 1 is 1/3, so 0.333333 confirms scipy.integrate is importable and running from the project environment.
Commit pyproject.toml and uv.lock with the project. Do not commit .venv unless the project has an unusual deployment policy.