ModuleNotFoundError в Python: почему возникает и как чинить
Знакомая пара строк в трейсбеке ломает запуск скрипта, который вчера работал. Разбираем, где Python ищет модули, почему поиск проваливается и как чинить каждую причину без гаданий.

Вы запускаете python app.py — и получаете ModuleNotFoundError: No module named 'requests'. Или того хуже: No module named 'myproject.utils', хотя файл utils.py лежит рядом. Ошибка одна, а причин у неё как минимум пять, и лечатся они по-разному. Разбираем механизм поиска модулей в Python 3.11–3.13, чтобы вместо перебора наугад вы за минуту понимали, куда именно смотреть.
Где Python на самом деле ищет модули
Когда интерпретатор встречает import requests, он идёт по списку путей в sys.path — сверху вниз, до первого совпадения. Список формируется при старте и выглядит примерно так:
- каталог со скриптом, который вы запустили (или пустая строка — текущий каталог — в интерактивном режиме);
- пути из переменной окружения
PYTHONPATH, если она задана; - стандартная библиотека самого интерпретатора;
- каталог
site-packagesтого окружения, из которого запущенpython.
Посмотреть реальный список для вашего запуска можно так:
import sys
for path in sys.path:
print(repr(path))
Если модуля нет ни в одном из этих каталогов — вы получаете ModuleNotFoundError. Дальше вопрос только в том, какой из пунктов у вас сломан.
Почти всегда ModuleNotFoundError означает не «пакет не установлен», а «установлен не в то окружение, из которого вы запускаете python». Это причина номер один.
Причина 1: пакет установлен не в то окружение
Классика: pip install requests прошёл успешно, а импорт падает. В системе стоит несколько Python — системный, из Homebrew, из виртуального окружения — и ваш pip положил пакет в один, а python запускается из другого.
Проверьте, что pip и python — из одного места. Надёжный способ — не звать pip напрямую, а вызывать его как модуль нужного интерпретатора:
# Куда смотрит python
python -c "import sys; print(sys.executable)"
# Ставим строго в это окружение
python -m pip install requests
# Проверяем, что пакет виден
python -c "import requests; print(requests.__version__)"
Форма python -m pip гарантирует, что установка идёт в то же окружение, из которого вы потом запускаете код. Разнобой между pip и python — источник большей части этих ошибок на новых машинах.
Виртуальное окружение не активировано
Если вы работаете в venv, пакет ставится внутрь него, но при незапущенной активации python берётся системный — без ваших зависимостей. Проверка та же: sys.executable должен указывать внутрь каталога окружения (например, .../.venv/bin/python). Если указывает на /usr/bin/python3 — окружение не активировано.
# Linux / macOS
source .venv/bin/activate
# Windows PowerShell
.venv\Scripts\Activate.ps1
Причина 2: имя пакета для установки не совпадает с именем для импорта
Это ловушка, о которой новички не догадываются. Имя в pip install и имя в import — разные строки, и совпадают они не всегда.
| Команда установки | Как импортируется |
|---|---|
pip install beautifulsoup4 | import bs4 |
pip install pillow | import PIL |
pip install PyYAML | import yaml |
pip install scikit-learn | import sklearn |
pip install python-dateutil | import dateutil |
Если вы уверены, что установили пакет, но импорт по «логичному» имени падает — проверьте на странице проекта на PyPI, как он импортируется на самом деле. Устанавливать по имени из ошибки бесполезно: pip install bs4 либо не найдёт ничего, либо поставит не то.
Причина 3: свой пакет не находится из-за структуры и запуска
Ошибка вида No module named 'myproject.utils' означает, что проблема не в стороннем пакете, а в том, как Python видит ваш собственный проект. Возьмём структуру:
myproject/
__init__.py
main.py
utils.py
services/
__init__.py
api.py
В main.py написано from myproject.utils import clean, и запуск падает. Причина: когда вы делаете python myproject/main.py, в sys.path попадает каталог myproject/, а не родительский. Пакета myproject по этому пути нет — есть только его содержимое.
Два рабочих решения.
Запуск как модуля из корня проекта
# Находясь на уровень выше папки myproject
python -m myproject.main
Флаг -m добавляет в sys.path текущий каталог, и myproject становится видимым как пакет. Абсолютные импорты вида from myproject.utils import clean начинают работать.
Установка проекта в редактируемом режиме
Если у проекта есть pyproject.toml, поставьте его один раз в окружение:
pip install -e .
После этого myproject импортируется откуда угодно, а правки в коде подхватываются без переустановки. Это стандартный способ для проектов, которые вы разрабатываете, а не просто ставите.
С Python 3.3+ __init__.py формально необязателен — работают неявные пакеты-пространства имён. Но для обычного проекта явный __init__.py предсказуемее и снимает часть неоднозначностей, поэтому его стоит держать.
Причина 4: относительные импорты запущены напрямую
Строка from .utils import clean внутри main.py при запуске python myproject/main.py даёт ImportError: attempted relative import with no known parent package. Относительный импорт работает только тогда, когда модуль исполняется как часть пакета — то есть через python -m myproject.main. Запуск файла напрямую делает его модулем верхнего уровня __main__, у которого нет «родителя» для точки.
Правило простое: точки в импортах требуют запуска через -m из корня. Если запускаете файл по пути — используйте абсолютные импорты.
Причина 5: файл называется как стандартный модуль
Вы создали random.py или email.py в своём проекте, а потом import random в другом файле подтягивает ваш файл вместо стандартной библиотеки — потому что каталог со скриптом стоит в sys.path раньше стандартной библиотеки. Иногда это выливается прямо в ModuleNotFoundError при импорте внутри вашего же файла, иногда — в странные AttributeError. Переименуйте файл и удалите рядом лежащий random.pyc или каталог __pycache__.
Быстрая диагностика: три команды
Прежде чем что-то менять, соберите факты. Эти команды отвечают на вопрос «где я и что видит Python» без догадок:
python -c "import sys; print(sys.executable)"— какой именно интерпретатор запускается. Сверьте с окружением, в которое ставили пакет.python -m pip list— что реально установлено в этом окружении. Если пакета в списке нет — ставьте черезpython -m pip install.python -c "import sys; print('\n'.join(sys.path))"— где идёт поиск. Убедитесь, что нужный каталог в списке есть.
Если ничего не помогло
ModuleNotFoundError: No module named 'pip'— сломано само окружение. Пересоздайтеvenvзаново, это быстрее, чем чинить.- Пакет в
pip listесть, но импорт падает — почти наверняка вы запускаете другойpython, чем тот, куда ставили. Вернитесь кsys.executable. - Работает в терминале, падает в IDE — IDE использует свой интерпретатор. В настройках проекта укажите путь к нужному
pythonиз вашего окружения. - Работает локально, падает в Docker или CI — рабочий каталог и
PYTHONPATHв контейнере другие. ПроверьтеWORKDIRи как именно вызывается запуск.
Что настроить, чтобы ошибка не возвращалась
Разовая починка не спасает от повтора на следующей машине. Что стоит сделать один раз:
- заведите
venvпод каждый проект и ставьте зависимости только черезpython -m pip; - зафиксируйте зависимости в
requirements.txtилиpyproject.toml, чтобы окружение восстанавливалось командой, а не по памяти; - для проектов, которые редактируете, используйте
pip install -e .— это снимает почти все вопросы с импортом собственных пакетов; - в IDE явно выберите интерпретатор проекта, чтобы запуск из редактора и из терминала совпадали.
Инвалидация кеша __pycache__ и тонкости importlib — отдельная тема; здесь мы разбирали только диагностику самого ModuleNotFoundError.
Поиск источников: Реальные статьи и книги со ссылками, библиография по ГОСТ
Спросить за 15 ₽Источники: Python docs — The import system, Python docs — sys.path
Частые вопросы
У меня Python 3.9, а не 3.13 — советы подойдут?
Я поставил пакет, pip list его показывает, но импорт всё равно падает. Почему?
В чём разница между ModuleNotFoundError и ImportError?
Нужен ли файл __init__.py в каждой папке?
Код работает в терминале, но падает в PyCharm или VS Code. Что делать?
Помогает ли добавление пути через sys.path.append?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.