Why does Python say ModuleNotFoundError when the package is installed?
Almost every case comes down to the same thing: the interpreter running your script is not the interpreter the package was installed into. Python does not have one global set of packages, it has one set per environment, and the two commands you typed can easily be talking to different ones.
The quickest way to prove this is to print the interpreter path and the module search path from inside the failing script itself, rather than from a shell. Comparing that against where the installer reported putting the package usually reveals the mismatch immediately.
Several situations produce it.
- An active virtual environment when installing but not when running, or the reverse. Editors are a frequent culprit because they select an interpreter independently of your terminal.
- Multiple Python versions installed side by side, where the plain command points at one and the versioned command at another. Invoking the installer as a module of a specific interpreter removes the ambiguity.
- Installing with elevated privileges, which places the package in a system location a user-level interpreter may not read.
There is also a category that has nothing to do with installation. A local file or directory whose name shadows the package will be found first, because the script's own directory sits at the front of the search path. A file named after a library you are importing breaks that import in a way that looks identical to a missing package.
Finally, the distribution name and the import name are not always the same. Several well known libraries are installed under one name and imported under another, so an install that genuinely succeeded can still be followed by an import that fails. Checking the project documentation for the correct import name resolves that case quickly.