TL;DR: if pip install paramiko said success and the import still fails, pip almost certainly installed paramiko for a different Python than the one running your code. Do not reinstall with bare pip. Find the interpreter that runs the code, then install through it with python -m pip install paramiko, and verify with that same interpreter. That one change fixes the venv-not-activated, multiple-Pythons, IDE, Jupyter, cron, and service-user variants of this error.

```text
ModuleNotFoundError: No module named 'paramiko'
```

Search that created the source thread:

```text
paramiko+No+module+named+pip+install
```

## Steps

### 1. Print the interpreter that actually fails

Run this with the exact command, working directory, and environment you use to run the failing script. Not in a different terminal you happen to have open.

```bash
python -c "import sys; print(sys.executable); print(sys.version)"
python3 -c "import sys; print(sys.executable); print(sys.version)"
```

Expected output: one path per command, for example a path inside your project .venv folder, a system python3 path, or a conda env path. Success check: note the path from the command that matches how the script is really launched. An IDE, Jupyter kernel, cron job, systemd unit, or Docker entrypoint may each use a different one.

### 2. Print where bare pip installs

```bash
pip --version
pip show paramiko
python -m pip --version
```

Expected output: pip --version ends with a python version and a site-packages path. pip show paramiko prints a Location line when it finds the package. Success check: compare the pip --version path with step 1. If pip belongs to a different folder or a different python version than sys.executable, you have found the mismatch and bare pip was the problem.

### 3. Install through the failing interpreter

Use the interpreter from step 1 as the module runner for pip. That guarantees the package lands in the site-packages that interpreter searches.

```bash
python -m pip install paramiko
```

Variants, same idea: if the script runs under python3, use python3 -m pip install paramiko. On Windows when the script is started with the py launcher, use py -m pip install paramiko. In Jupyter, run the magic form in a cell, %pip install paramiko, then restart the kernel. In conda, activate the env first, then use python -m pip install paramiko inside it, or install the conda package for paramiko in that env.

Expected output: Successfully installed paramiko, plus its dependencies bcrypt, cryptography, and pynacl, or Requirement already satisfied lines that name a Location inside the step 1 environment. Success check: the install location and sys.executable now share the same environment prefix.

### 4. Verify in the same interpreter, not with bare pip

```bash
python -m pip show paramiko
python -c "import paramiko; print(paramiko.__version__); print(paramiko.__file__)"
```

Expected output: pip show prints Name, Version, and Location, and the import prints a version number and a file path inside the same environment as sys.executable. Success check: run the original script the original way. If the terminal import works but the script still fails, the script is launched by something else: go back to step 1 and print sys.executable from inside the script itself, at its top, and use that path.

### 5. Make it permanent in the project

A one-off shell install disappears in the next fresh environment. Declare the direct dependency.

```bash
python -m pip show paramiko
```

Add a paramiko line to requirements.txt, or add paramiko as a dependency in pyproject.toml with your project tool, pinned or bounded the way your project handles other dependencies. Then, in CI and containers, install and run with the same interpreter: create the venv, activate it, upgrade nothing by hand with a second pip, and use python -m pip for installs in the Dockerfile or CI step too.

Expected output: a clean checkout, a new venv, and an install from the project dependency file passes the step 4 import check. Success check: nobody on the team needs a manual pip install paramiko step any more.

### 6. Rule out the remaining hiding places

If steps 1 to 4 match and the import still fails, check these in order:

1. Virtualenv not activated in the shell that ran the install. Activation lasts one terminal session only. Activate the env, confirm sys.executable points inside it, then repeat step 3.
2. Editor interpreter. In VS Code and similar editors, select the interpreter whose path equals step 1 output. The integrated terminal can be right while the run button uses another env.
3. A different user ran the install. An install done with sudo, or as an administrator, or with a user-only flag, is visible to one user and one interpreter and invisible to a service account, cron, or a web worker running as someone else. Repeat step 3 as the user and interpreter that run the code, inside a venv owned by that user.
4. A local file shadows the name in reverse. A file named paramiko in your project does not cause a missing-module error for paramiko itself, but a broken or empty folder with that name on sys.path can be picked up instead of the installed package. Rename it and retry.
5. PYTHONPATH points at another environment. Print sys.path in the failing run and look for site-packages folders from a different venv or python version ahead of the correct one. Remove the stale entry instead of installing around it.
6. The install itself failed partway. If python -m pip install paramiko errors while building cryptography, bcrypt, or pynacl on an old platform, that is a build problem, not this mismatch. Upgrade pip inside the same interpreter first with python -m pip install --upgrade pip, then retry, and prefer a current python with prebuilt wheels.

Expected output: one of the six explains the case, or the import now works. Success check: the import succeeds when the script is launched the production way, not only in an interactive shell.

## When this applies

- pip install paramiko reported success, and import paramiko still raises ModuleNotFoundError.
- pip show paramiko finds the package, but python -m pip show paramiko in the running environment does not, or shows a different Location.
- The code works in one terminal and fails in an IDE, Jupyter, cron, a service, CI, or a container.
- The machine has more than one Python: system python plus venv, conda, Homebrew, or a Windows py launcher install.

## When this does not apply

- Paramiko was never installed anywhere. The short form, python -m pip install paramiko in an activated venv, is still the fix, and steps 1 to 4 confirm it in minutes.
- Paramiko imports, then fails with No module named nacl on an Ed25519 key. That is the optional PyNaCl backend missing, a different package and a different fix.
- Paramiko imports, then fails on a removed name such as DSSKey, or on SSH authentication, host keys, or timeouts. Those are version and connection problems, not an install-location problem.

### Variant: import works in terminal, fails in Jupyter

The notebook kernel is its own interpreter and often not the one in your shell PATH. Print sys.executable in a notebook cell, install with the %pip magic so the install targets the kernel, and restart the kernel so it picks up the new package.

### Variant: works locally, fails in Docker or CI

The image or CI job created one env at build time and runs another, or it installed with a pip belonging to the base image and runs a venv python. In the Dockerfile or CI config, create the venv first, then do every install and the final run with that venv python and python -m pip, so build and run cannot diverge.

### Variant: pip and python report the same version but still mismatch

Same version number is not same interpreter: python 3.12 from the OS and python 3.12 from Homebrew or conda are different installs with different site-packages. Trust full paths, not version numbers. Compare sys.executable, pip --version output, and the Location line character by character in folder terms.

## Why it happens

pip is a separate program with its own target environment, and a machine normally has several Pythons. Bare pip installs into whichever environment that pip script was built for, which is decided by PATH order and history, not by the script you are about to run. The running interpreter only searches its own sys.path. If the two environments differ, the package genuinely exists on disk and genuinely does not exist for that interpreter, so both tools report the truth and the error looks impossible until you compare paths. Invoking pip as a module of the target interpreter removes the ambiguity, because the interpreter itself decides where its packages live.

## Compatibility

Paramiko 3.x and 4.x on supported CPython 3 versions, on Linux, macOS, and Windows. Paramiko depends on bcrypt, cryptography, and PyNaCl, which pip installs automatically; current releases ship prebuilt wheels for common platforms. The python -m pip pattern works with venv, virtualenv, conda envs, and system interpreters, and with pip versions that support being run as a module, which is every pip in current use.

## Edge cases and pitfalls

- Do not fix this with repeated bare pip installs, or with copying the paramiko folder between environments. Both hide the mismatch and break again on the next machine.
- Do not install with sudo to make it work. That installs for the system interpreter as another user and usually makes the service and venv cases worse.
- Requirement already satisfied can be the bug, not a reassurance: read its Location. If that folder is not on the failing interpreter sys.path, it was satisfied in the wrong env.
- Restart long-running processes after installing. A running worker, notebook kernel, or IDE debug session that started before the install may keep its old module search state; a fresh process is the honest test.
- Check the spelling of the import: the distribution and the import name are both paramiko, all lowercase. A failure after correcting the environment that mentions a differently spelled name is a typo, not an environment problem.
