Fundamentals

Fix ModuleNotFoundError: No Module Named openai

Your script says No module named openai even though pip said it installed. Learn why the interpreter and pip disagree, and fix it in three commands.

By the end of this guide you will know exactly which Python interpreter is running your script, why the package you installed is invisible to it, and which single command puts them back in agreement. The whole repair usually takes under three minutes once you can read the evidence, and the same reasoning fixes every future ModuleNotFoundError, not just this one.

This is one guide in Debugging Python AI Errors, the section that walks through the failures beginners hit in their first weeks of calling AI APIs.

Prerequisites

You need Python 3.10 or newer already on your machine. If it is missing, start with How to Install Python for AI on Windows, How to Install Python for AI Projects on Mac or How to Install Python for AI on Linux, then come back.

Everything below runs from a terminal opened in your project folder. Install the two packages this guide uses, always through python -m pip for the reason the whole page is about:

python -m pip install "openai>=1.40" "python-dotenv>=1.0"

The final smoke test calls the API, so keep your key in a .env file beside your script:

OPENAI_API_KEY=sk-your-key-here

Then add that file to .gitignore before you commit anything, because a key in a public repository is a key strangers can spend:

echo ".env" >> .gitignore

Step 1 — Make the script name its own interpreter

Start by reading the error itself, because it is more precise than it looks:

Traceback (most recent call last):
  File "/home/you/projects/ai-scripts/app.py", line 3, in <module>
    from openai import OpenAI
ModuleNotFoundError: No module named 'openai'

ModuleNotFoundError has one narrow meaning: Python searched every folder on its import path and found nothing called openai. It is not saying the package is broken, that your key is wrong, or that the network failed. It is saying "I looked, and it was not there." So the only useful question is where it looked.

An interpreter is the actual python program that reads and executes your file. Most computers have several: one that shipped with the operating system, one you installed yourself, one inside every virtual environment you have ever created, and sometimes one belonging to an editor or a notebook kernel. Each keeps its own private library folder, called site-packages. A package installed into one is completely invisible to the others.

sys.executable is the absolute path of the interpreter currently running your code. Put these two lines at the very top of the file that fails, above every other import:

import sys

print("Interpreter:", sys.executable)
print("Version:    ", sys.version.split()[0])
print("Looking for packages in:")
for path in sys.path:
    if path.endswith("site-packages"):
        print("  ", path)

Run the file exactly the way you normally run it — same terminal, same button, same notebook. Then run this in your terminal to see where pip is pointing:

python -m pip --version

The output ends with the interpreter pip belongs to, something like (python 3.12) preceded by its library path. If that path and the path from sys.executable are not the same, you have found your bug. Nothing is broken, corrupted or missing — you simply installed into one Python and ran under another.

Two lanes: where pip wrote the package and where Python searched for it The upper lane follows a pip install command into the global interpreter and its site-packages folder, where the openai package now lives. The lower lane follows the script, which starts under the virtual environment interpreter whose site-packages folder is empty, so the import raises ModuleNotFoundError. pip install openai what you typed Global Python usr/bin/python3 openai landed here its site-packages one machine, two separate libraries python app.py what you ran Venv Python .venv/bin/python No openai here ModuleNotFoundError
The package really was installed — just into the library folder of a different interpreter than the one that started your script.

Step 2 — Reinstall with python -m pip

The command pip install openai runs a standalone program called pip that your shell finds by scanning the folders listed in PATH and taking the first match. On a machine with three Pythons, that first match is a coin toss you did not know you were flipping.

The -m flag removes the guesswork. It means "run this module using the interpreter I just named", so python -m pip is always the pip belonging to that exact python. Whatever it installs lands where that interpreter will look:

python -m pip install openai

If you have several versions installed and want to be even more explicit, name the version directly. This is the safest form of the command on macOS and Linux, where python3 and python can differ:

python3.12 -m pip install openai

Watch the last line of the install output too. Pip finishes with either Successfully installed openai-1.x.x or Requirement already satisfied. That second message trips people up: it does not mean your script can import the package, only that this particular interpreter already has it. If you keep seeing "already satisfied" while your script keeps failing, you are still installing into the wrong Python and Step 3 is where you go next.

Make python -m pip your permanent habit. It costs six extra keystrokes and removes an entire category of error from your life.

Bare pip versus python dash m pip, step by step The left column shows a bare pip command being resolved by the shell PATH, leaving the target interpreter unknown and the import still failing. The right column shows python dash m pip naming the interpreter first, running pip inside it, and the import succeeding. Bare pip python -m pip Shell picks a pip first match on PATH Which Python? you cannot tell Script still fails ModuleNotFoundError You name Python the exact one you run pip runs inside it no PATH guesswork Import succeeds same interpreter
Both commands install a package; only the right-hand one guarantees it lands in the interpreter that will later run your script.

Step 3 — Activate the virtual environment first

A virtual environment is a private folder holding one interpreter and its own site-packages, so each project keeps its own package versions. Activating it rewires your shell so that plain python and plain pip both point inside that folder. Forget to activate and you are back to the system Python without any warning on screen.

Create and activate one in your project folder:

python -m venv .venv
source .venv/bin/activate

On Windows PowerShell the last line is different:

.venv\Scripts\Activate.ps1

The difference an activation makes is visible in one command. Before, your shell resolves python to the system copy; after, it resolves to the environment's copy, and the prompt gains a (.venv) prefix:

$ which python
/usr/bin/python3

$ source .venv/bin/activate

(.venv) $ which python
/home/you/projects/ai-scripts/.venv/bin/python

On Windows, use where python instead of which python. If your prompt has no (.venv) marker, the environment is not active, and every install you run is going somewhere else. Activation lasts only for that terminal window — open a new tab and you must activate again. That single fact explains most "it worked yesterday" reports. For the full walkthrough, including how to add the environment to .gitignore, read Create a Python Virtual Environment for AI.

Step 4 — Confirm the fix in two commands

Do not rerun your whole script to test a package install. Check the package first, then the import, so a failure tells you precisely which half is wrong.

pip show prints where a package actually lives:

python -m pip show openai

Read the Location: line it prints. That path must contain your .venv folder if you are working in a virtual environment. If it points at a system folder, your shell is still unactivated.

Now test the import on its own, with nothing else in the way:

python -c "import openai; print(openai.__version__)"

A version number means the problem is solved. Any traceback here is still an interpreter problem, not a code problem. Once both commands pass, run a real call to confirm the package works end to end:

import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()  # reads .env, which is listed in .gitignore

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Reply with the single word: ready"}],
)

print(response.choices[0].message.content)

If that script prints a word, your environment is healthy. If it prints an authentication complaint instead, the import is fine and you have moved on to a key problem — see Fix the 401 Unauthorized Error in OpenAI Python.

While the environment is working, record what is in it. A requirements.txt file lists every package and version you currently have, so you can rebuild the same environment on another machine, or after you delete a broken .venv and start over:

python -m pip freeze > requirements.txt

Rebuilding later is then two commands — create an environment, then python -m pip install -r requirements.txt — rather than a memory test.

Step 5 — Fix the editor and notebook cases

Editors and notebooks each hold their own interpreter setting, which is why the same folder can work in a terminal and fail behind a Run button.

In VS Code, open the command palette and choose the "Python: Select Interpreter" command, then pick the entry whose path ends in .venv/bin/python (or .venv\Scripts\python.exe on Windows). In PyCharm, the same setting lives under the project interpreter preferences, where you add an existing environment and browse to the same file. Both editors show the selected interpreter in the status bar; if it reads a bare version number with no project name, it is on the global Python. Choose a Code Editor for Python AI Work covers the setting in each editor in more detail.

In Jupyter, JupyterLab or Colab, the notebook runs under a kernel, and the kernel is its own interpreter. Installing from a terminal frequently misses it. Install from inside a cell instead, using the %pip magic command, which targets the running kernel by design:

%pip install openai

Restarting the kernel afterwards matters. A running kernel caches the list of modules it has already tried to import, so a package installed mid-session can stay invisible until the kernel starts fresh. Use the restart button in the toolbar, then rerun your cells from the top and confirm exactly as you did in the terminal:

import sys
print(sys.executable)

import openai
print(openai.__version__)
Decision tree from the printed interpreter path to the right fix Starting from the path printed by sys.executable, three branches lead to three fixes: a global system path means activate the environment and reinstall, a virtual environment path means install into it with python dash m pip, and an editor or kernel path means repoint the editor or install with the percent pip magic. sys.executable what path printed? A system path usr/bin or Program Your .venv path but import fails An editor path or a kernel path Activate .venv then install again Install into it python -m pip install Repoint the tool or use %pip install
Read the path your script printed, follow its branch, and you land on the one fix that applies to your machine.

Quick reference: symptom to wrong interpreter

Match what you observed on the left to the interpreter that is out of step, then apply the fix.

What you seeInterpreter at faultFix
Fails in the terminal right after a successful installThe pip your shell chose from PATHpython -m pip install openai
Works in the terminal, fails on the editor's Run buttonThe editor's configured interpreterSelect the .venv interpreter in the editor
Works in the terminal, fails in a notebook cellThe notebook kernel%pip install openai in a cell, then restart
Worked yesterday, fails in a new terminalThe system Python, environment not activatedsource .venv/bin/activate

Troubleshooting

ModuleNotFoundError: No module named 'openai' in a file you named openai.py. Python searches your current folder before its libraries, so your own file shadows the real package and the import returns your empty file. Rename the file to something like chat_test.py and delete any __pycache__ folder next to it.

AttributeError: module 'openai' has no attribute 'OpenAI'. The import worked, but an old 0.x release of the library is installed and it has no OpenAI client class. Upgrade in place with python -m pip install --upgrade "openai>=1.40".

bash: pip: command not found. No standalone pip executable exists on your PATH, which is common on fresh macOS and Linux installs. This is the error python -m pip was designed for — use it and the problem disappears.

error: externally-managed-environment. Your operating system protects its own Python from stray installs, mostly on recent Linux distributions and Homebrew Python. Do not force it with --break-system-packages; create a virtual environment as in Step 3 and install there instead.

If the traceback you are staring at looks nothing like these, Read a Python Traceback in Five Minutes shows you how to find the one line that names the real cause.

When to use this vs. alternatives

  • Use a virtual environment per project for anything you will run more than once. It costs one command, keeps each project's package versions apart, and makes ModuleNotFoundError rare because there is only ever one interpreter in play.
  • Install into the global Python only for a genuinely throwaway experiment, and expect to hit version conflicts the moment a second project wants a different release of the same library. On systems that raise externally-managed-environment, this option is closed to you anyway.
  • Use conda or a similar manager when your work needs heavy scientific packages that ship compiled code. It solves a different problem — binary dependencies — but it adds yet another interpreter to your machine, so keep applying the python -m pip habit inside a conda environment too.

The lasting lesson is smaller than the error message suggests. Python does not have one library folder; it has one per interpreter, and every install command silently chooses which folder it writes to. Print sys.executable, install with python -m pip, activate before you install, and the most common beginner error in Python stops happening to you. Back to Debugging Python AI Errors.

Frequently asked questions

Why does Python say no module named openai when pip already installed it?

Because the pip you ran and the Python that ran your script are two different programs. Pip wrote the package into one interpreter's library folder, and your script started under a second interpreter that cannot see that folder. Running python -m pip install openai forces both halves to be the same interpreter.

What does python -m pip install do differently from pip install?

The -m flag tells a specific Python interpreter to run pip as one of its own modules. The package therefore lands in that exact interpreter's library folder. A bare pip command is a separate executable chosen by your shell's PATH, and on most machines several of them exist side by side.

How do I know which Python is running my script?

Add import sys and print(sys.executable) as the first two lines of the failing file, then run it the same way you always do. The printed path is the exact interpreter in use. Compare it with the path shown by python -m pip --version and the mismatch becomes obvious.

Why does my code work in the terminal but fail in VS Code or PyCharm?

Editors keep their own interpreter setting, and a fresh project usually points at the system Python rather than your project's virtual environment. The terminal run uses the activated environment, the editor run does not. Switch the editor's interpreter to the one inside your .venv folder and both agree again.

How do I install a package from inside a Jupyter notebook?

Run %pip install openai in a notebook cell. The percent sign makes it a notebook magic command that installs into the kernel currently executing your cells, which is the only interpreter that matters there. A plain pip install in a terminal often targets a different Python than the kernel.