ModuleNotFoundError: No module named 'mysql' means the MySQL connector is not installed in the interpreter running your script. The package you almost certainly want is mysql-connector-python, and the most common cause of the error persisting after installing it is that pip installed into a different Python than the one running your code.
The quick fix#
python -m pip install mysql-connector-python
import mysql.connector
conn = mysql.connector.connect(
host="localhost", user="root", password="secret", database="shop"
)
print(conn.is_connected())
conn.close()
Use python -m pip rather than plain pip. It guarantees the install goes into the same interpreter you are about to run, which removes the single most common cause of this error surviving the fix.
Why the names do not match#
You install mysql-connector-python but import mysql.connector. That mismatch is normal in Python — the name on PyPI and the name you import are set independently. It is why searching for the error text alone often leads people to install the wrong thing.
The three MySQL libraries#
| Install | Import | Notes |
|---|---|---|
mysql-connector-python |
mysql.connector |
Official from Oracle, pure Python, easiest to install |
PyMySQL |
pymysql |
Pure Python, popular with SQLAlchemy and Django |
mysqlclient |
MySQLdb |
C extension, fastest, needs build tools installed |
Pick one. Installing all three does not help and makes it harder to work out what your code is actually using.
When installing did not fix it#
The install almost always succeeded — into a different Python. Check both sides:
python -c "import sys; print(sys.executable)"
python -m pip --version
The path printed by the first command and the path inside the second should share a prefix. If they do not, you have more than one Python and pip belongs to the other one.
python -m pip show mysql-connector-python
If that reports nothing while pip show finds it, that is the mismatch confirmed. Always install with python -m pip.
Virtual environments#
Packages installed globally are not visible inside a virtual environment, and the other way round:
python -m venv .venv
source .venv/bin/activate # macOS and Linux
.venv\Scripts\activate # Windows
python -m pip install mysql-connector-python
python -m pip freeze > requirements.txt
If the prompt does not start with (.venv), activation did not take effect and you are installing somewhere else.
VS Code#
VS Code picks its own interpreter, which is often not the one in your terminal. Open the command palette with Ctrl+Shift+P, run Python: Select Interpreter, and choose the one inside your project’s .venv. Then check from inside the editor:
import sys
print(sys.executable)
Jupyter#
A notebook has its own kernel, which may be a different environment again. Install from inside the notebook so it cannot disagree:
import sys
!{sys.executable} -m pip install mysql-connector-python
Then restart the kernel. Python caches imported modules, so a newly installed package is not visible until the kernel restarts.
Docker#
The package has to be installed inside the image, not on your machine:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
If you added the dependency after building, rebuild — the layer is cached and will not pick up a new requirements file on its own.
Connecting properly once it imports#
import os
import mysql.connector
from mysql.connector import Error
try:
conn = mysql.connector.connect(
host=os.environ.get("DB_HOST", "localhost"),
user=os.environ["DB_USER"],
password=os.environ["DB_PASSWORD"],
database=os.environ["DB_NAME"],
)
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT id, name FROM products WHERE price < %s", (20,))
for row in cursor.fetchall():
print(row["id"], row["name"])
except Error as error:
print("Database error:", error)
finally:
if "conn" in locals() and conn.is_connected():
cursor.close()
conn.close()
Two things worth copying: credentials come from environment variables rather than the source file, and the query uses %s placeholders rather than string formatting. Building SQL with f-strings is how SQL injection happens.
Questions people ask#
Which connector should I choose?
mysql-connector-python if you want the fewest installation problems. PyMySQL if you are using SQLAlchemy or Django. mysqlclient only when you have measured that connector speed matters.
Does this work with MariaDB?
Yes. MariaDB speaks the MySQL protocol and all three libraries connect to it. There is also a dedicated mariadb package if you need MariaDB-specific features.
Why does it work in the terminal but not in my IDE?
Different interpreter. Print sys.executable in both places — the paths will differ, and pointing the IDE at the right one fixes it.
I get a build error installing mysqlclient
That package compiles C code and needs MySQL development headers plus a compiler. Unless you specifically need it, switch to mysql-connector-python, which is pure Python and installs anywhere.
Where to go next#
- Python virtual environments — the root cause of most import errors.
- Fixing ModuleNotFoundError for pandas — the same diagnosis, different package.
- Working with databases — SQL basics and safe queries.