You install PySerial, write serial.Serial("COM3", 9600), run the script, and Python says:
Traceback (most recent call last):
File "C:\Users\you\project\main.py", line 3, in <module>
ser = serial.Serial("COM3", 9600)
^^^^^^^^^^^^^
AttributeError: module 'serial' has no attribute 'Serial'
The annoying part: the import worked. Python did find a module called serial. It's just not a working PySerial. There are three possible reasons, and one command tells you which one you have.
What the Error Means
import serial worked, so Python loaded something called serial. The error says that thing has no Serial class. PySerial defines Serial in serial/__init__.py. So either Python loaded a different serial, or it found PySerial's folder with that file missing.
Step 1: Find Out What serial Really Is
Print where Python loaded it from, and list what pip has installed:
python -c "import serial; print(serial.__file__)"
python -m pip list | findstr serial
On macOS and Linux use grep serial instead of findstr serial. Use python -m pip instead of a bare pip, so pip and Python are guaranteed to be the same installation (more on that below). Then match what you see:
| What you see | What it means | Fix |
|---|---|---|
serial.__file__ is None
|
An empty folder named serial, or a damaged PySerial install |
Cause 3 |
| The path points into your own project | Your own file or folder named serial hides the package |
Cause 1 |
pip list shows serial, not pyserial
|
The wrong package is installed | Cause 2 |
I reproduced all three in a fresh virtual environment (PySerial 3.5, Python 3.14), so the outputs below are real.
Cause 1: Your Own File Named serial.py
If your project has a file named serial.py, or a folder named serial, Python imports that instead of PySerial, because it looks in your script's folder first. I tried it: a serial.py next to a script gave me the same AttributeError. In that case serial.__file__ points at your own file.
Rename it, for example to serial_reader.py, and delete the __pycache__ folder next to it so Python doesn't keep using the old copy. This is the usual cause when you name your test file after the library.
Cause 2: The Wrong Package
PySerial installs with pip install pyserial, but you import it as serial. There's a different package on PyPI that is literally called serial, and pip install serial gets you that one. I tried it: it installs serial 0.0.97, import serial works, and serial.Serial doesn't exist.
python -m pip uninstall serial
python -m pip install pyserial
If both are installed, remove both first so you get a clean copy:
python -m pip uninstall serial pyserial
python -m pip install pyserial
Cause 3: A Damaged Install (the Confusing One)
This is the sneaky one. pip list still shows pyserial 3.5 and everything looks fine, but serial.__file__ prints None.
On the PC I used for this post, pip said pyserial 3.5, but serial/__init__.py was missing from the install folder, even though pip's own record lists it. Something had deleted it, and I couldn't tell what. Without that file Python treats the serial folder as an empty "namespace package", which is why __file__ is None and Serial doesn't exist.
The fix is to reinstall and force pip to replace the files:
python -m pip install --force-reinstall pyserial
I tested this in a fresh virtual environment: I deleted serial/__init__.py, got the error, ran the command, and serial.Serial worked again.
One Script That Checks All Three
This script prints the path, checks for Serial, shows which of the two packages is installed, and tells you the cause and the fix. Run it with the same Python you use for your project:
# Diagnose: AttributeError: module 'serial' has no attribute 'Serial'
import importlib.metadata as md
import serial
def installed(name):
try:
return md.version(name)
except md.PackageNotFoundError:
return None
print("serial.__file__ :", serial.__file__)
print("has serial.Serial:", hasattr(serial, "Serial"))
print("installed pyserial:", installed("pyserial") or "no")
print("installed serial :", installed("serial") or "no")
if serial.__file__ is None:
print("-> 'serial' is an empty folder or a damaged install. Fix: pip install --force-reinstall pyserial")
elif hasattr(serial, "Serial"):
print("-> PySerial looks fine.")
elif installed("serial"):
print("-> The wrong package is installed ('serial', not 'pyserial'). Fix: pip uninstall serial, then pip install pyserial")
else:
print("-> A file or folder named 'serial' in your project is hiding PySerial (see the path above). Rename it.")
This is the real output on the damaged install described above:
serial.__file__ : None
has serial.Serial: False
installed pyserial: 3.5
installed serial : no
-> 'serial' is an empty folder or a damaged install. Fix: pip install --force-reinstall pyserial
I ran the script against all four states (healthy, damaged, a serial.py in the way, and the wrong package), and it named the right cause every time.
Check You Are Using the Same Python
Lots of machines have more than one Python: the Microsoft Store one, one from python.org, one inside a virtual environment, and whichever your editor picks. A bare pip can belong to a different Python than the one running your script, so you fix one installation and test another.
Ask the Python that runs your script which one it is, and have the same Python run pip:
python -c "import sys; print(sys.executable)"
python -m pip list
python -m pip always uses the Python you typed. In VS Code, check the interpreter in the bottom-right corner: the Run button uses that one, which isn't necessarily the one in your terminal.
How to Avoid It
Never name your own file serial.py or pyserial.py, and never name a folder serial. Use a name like serial_reader.py or read_port.py. Make one virtual environment per project and install with python -m pip install pyserial, so the package is never mixed up with another project's. And if you ever see serial and pyserial together in pip list, remove both and reinstall pyserial alone.
If You Get a Different Error
The AttributeError is only one PySerial error. If Python says ModuleNotFoundError: No module named 'serial', PySerial is not installed in the Python you are running, which is a different problem: see ModuleNotFoundError After pip install? Here's the Fix. If the import works but opening the port fails with "Access is denied", see PySerial Access Is Denied on a COM Port.
If you are using PySerial to talk to an Arduino, Why delay() Freezes Your Arduino and How to Use millis() Instead covers the other side of the connection, and Architecting Autonomous AI Agents with Hardware Integration shows PySerial inside a bigger project.
The Short Version
module 'serial' has no attribute 'Serial' means Python imported something called serial that isn't a working PySerial. Print serial.__file__ and check pip list. None means a damaged install, a path inside your own project means a file is in the way, and serial in the pip list means the wrong package.
Download the code: the diagnostic script is on GitHub in Python-projects/Troubleshooting/pyserial-no-attribute-serial.
Originally published on my blog. I post new C, Python and AI-agent guides there regularly.
Top comments (0)