pythonpippython-import

Python "is not a package" error but it's in sys.path and shows up in pip list


I'm trying to get the websockets tutorial code running and I'm getting this error: ModuleNotFoundError: No module named 'websockets.asyncio'; 'websockets' is not a package. I know there are several questions about this already, and I've tried all the suggestions found there, to no avail.

My code:

import asyncio
import sys

from websockets.asyncio.server import serve


async def handler(websocket):
    while True:
        message = await websocket.recv()
        print(message)


async def main():
    async with serve(handler, "", 8001):
        await asyncio.get_running_loop().create_future()  # run forever


if __name__ == "__main__":
    asyncio.run(main())

I know Python looks for package in sys.path. When I print sys.path, I get:

['/Users/taylorwofford/Desktop', '/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages', '/Library/Frameworks/Python.framework/Versions/3.13/lib/python313.zip', '/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13', '/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/lib-dynload']

When I open /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages, lo and behold, there it is:


taylorwofford@Taylors-Air \~ % cd /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages
taylorwofford@Taylors-Air site-packages % ls
Django-5.1.2.dist-info      pip-24.2.dist-info
README.txt          sqlparse
asgiref             sqlparse-0.5.1.dist-info
asgiref-3.8.1.dist-info     websockets <--- here!!!
django              websockets-13.1.dist-info
pip
taylorwofford@Taylors-Air site-packages %

I thought maybe it had something to do with my Python version. I'm running 3.13:


taylorwofford@Taylors-Air site-packages % python3 --version
Python 3.13.0

I verified the expected Python was being run in the script. I added print(sys.version_info) and the result was sys.version_info(major=3, minor=13, micro=0, releaselevel='final', serial=0) -- 3.13, as expected. When I run python3 pip list, I get


taylorwofford@Taylors-Air site-packages % python3 pip list
Package    Version

-----------------

asgiref    3.8.1
Django     5.1.2
pip        24.2
sqlparse   0.5.1
websockets 13.1 <--- here!

I'm not sure what else to do. Everything looks correct to me.

I tried checking which Python version I'm using, confirmed the script I'm trying to run is using the same version, checked the package I'm looking for is installed via pip3, and confirmed it's located in a directory in sys.path.


Solution

  • When Python runs a script it prepends script's directory to sys.path. This allows to import additional modules from the script's directory. Unfortunately it means you can easily overshadow modules/packages from the standard library or 3rd-party modules installed with pip.

    Your script is named websockets.py. With sys.path modification explained above import websockets imports your script and import websockets.asyncio fails because your script is not a package, it's a module without subpackages.

    To fix the problem rename the script to something unique or not importable.

    mv websockets.py websockets-test.py
    

    should help.

    Note for the future — don't give you modules, packages and scripts the same names as modules/packages from the standard library or 3rd-party modules. Never import email from your script named email.py. Never import test from your script named test.py. email (without extension) or test are ok, they're not importable so they don't shadow Python packages; executable script test shadows /bin/test though.