# Install Python packages inside 3D Slicer's bundled Python

Install third-party Python packages in 3D Slicer 5.x: use slicer.util.pip_install on Slicer's own bundled Python 3.9, classify pip_install failures (wrong package name, no network, CPU-only torch, numpy upgrade access-denied) from their error text, and verify with an immediate import.

Exact reference: {"kind":"skill_version","skill_id":"skl_KgYll7iviNr89r8wC4bylg","version_id":"skv_dzdnMtZ_0wzdTW3MFkn4aQ"}

Applicability: [{"constraint":">=5.0","technology":"3D Slicer","version_scheme":"semver"}]

# Install Python packages inside 3D Slicer's bundled Python

Use this when a Slicer script, scripted module, or Python-interactor session needs
a package that is not part of Slicer's bundled Python. Slicer 5.x ships its own
Python 3.9 with its own site-packages — the system Python is irrelevant and must
never be mixed in.

## 1. Always use Slicer's own pip through `slicer.util.pip_install`

From the Python interactor (View / Python Interactor):

```python
import slicer
slicer.util.pip_install('requests')                                  # one package
slicer.util.pip_install('ipywidgets pandas ipyevents ipycanvas')     # space-separated = multiple
slicer.util.pip_install('--upgrade pillow --force-reinstall')        # pip flags pass straight through
```

Do **not** run the system `pip`, and do **not** copy packages from the system
`site-packages` into Slicer's. Core developers state plainly that copying binary
packages from another Python into Slicer's site-packages does not work and can
prevent Slicer from starting. If you are outside the interactor, use Slicer's
Python executable directly:

- Windows: `PythonSlicer.exe -m pip install [package]` (from Slicer's `bin` directory)
- macOS: `/Applications/Slicer.app/Contents/bin/python-real -m pip install [package]`

A pip upgrade notice like "To update, run: python-real.exe -m pip install --upgrade pip"
is followed the same way.

## 2. Classify the failure from the error text FIRST

### `ModuleNotFoundError: No module named 'X'` after installing

Two distinct causes, check in order:

1. **The pip install actually failed.** `pip_install` raises
   `subprocess.CalledProcessError: Command '[...PythonSlicer... -m pip install X]'
   returned non-zero exit status 1` when pip fails, so look at the pip output
   above it — the real cause is there.
2. **Wrong package name.** The classic: `pip_install('opencv')` fails with
   `ERROR: Could not find a version that satisfies the requirement opencv
   (from versions: none)`. The PyPI name is `opencv-python`:
   `slicer.util.pip_install('opencv-python')`. (Alternatively install the
   SlicerOpenCV extension, which provides OpenCV with Python bindings.)

### `Could not find a version that satisfies the requirement X (from versions: none)`

- If it happens for **every** package (test with `pip_install('requests')`),
  pip cannot reach the index — no network, proxy, or firewall. Fix the network,
  not the package.
- If only one package fails, the name is wrong or no wheel exists for Slicer's
  Python (e.g. a package with no Python 3.9 wheel).

### Importing `torch` gets the CPU build or fails

`pip_install('torch')` installs the CPU-only wheel by default. For a CUDA build,
pass the PyTorch CUDA index through to pip (flags pass through, see above):

```python
slicer.util.pip_install('torch --index-url https://download.pytorch.org/whl/cu118')
```

Pick the `cuXXX` tag that matches your GPU driver — pytorch.org's Get Started
page lists the current tags. Note that torch is large; module developers
typically gate it behind an on-demand check in the module's logic
(`try: import torch / except ModuleNotFoundError: slicer.util.pip_install(...)`)
rather than at module load, so a failed download never bricks the module.

### `pip install numpy -U` fails from the interactor with access-denied errors

Slicer modules import numpy at startup, so Windows refuses to replace the file
while Slicer is running. Install it from the command line instead, with Slicer
**not running**:

```
PythonSlicer.exe -m pip install numpy -U
```

And think twice before doing it at all: Slicer builds pin numpy (the 5.4-era
builds ship numpy 1.26.4), and the numpy 2.0 release was announced on the Slicer
forum with an explicit warning not to upgrade numpy in Slicer because it breaks
builds. Only upgrade numpy if a required package genuinely demands it, and
verify Slicer still starts and imports its modules afterward.

## 3. Verify in the interactor, restart if needed

After a successful install, import the package immediately in the interactor to
confirm. Most packages work without a restart; pure-Python installs that pull
upgraded dependencies of already-imported packages may need one — the console
has a `restart()` command for exactly this. If the import fails after a
successful install, restart Slicer and try the import again before doing
anything else.


## Supporting basis and limitations

Built from the 3D Slicer Discourse threads 'Slicer-Python Packages Use and Install' (core-developer answers on pip_install usage, system-pip mixing, and the numpy -U access-denied workaround via PythonSlicer.exe), 'Error when installing opencv with Python Interactor on mac' (opencv vs opencv-python naming), 'Numpy 2.0 arrives with breaking changes' (do-not-upgrade warning), and the 'Issues with Loading MUST-Segmenter Module' thread (torch install failure trace and the checkRequirements/pip_install on-demand pattern).

## Change and rationale

New skill: install Python packages inside 3D Slicer's bundled Python.

Slicer 5.x ships its own Python 3.9 with its own site-packages, and the recurring failure pattern is users treating it like the system Python — copying site-packages, using the system pip, installing the wrong PyPI name (opencv vs opencv-python), getting the CPU-only torch build, or breaking numpy. This skill classifies the install failure from the pip error text before prescribing the fix.
