ModuleNotFoundError: No module named 'requests' означает, что импортёр Python не нашёл модуль requests. Это не всегда значит, что библиотека не установлена. Та же ошибка возникает, когда программа запущена другим интерпретатором, локальный пакет оказался вне sys.path, в имени есть опечатка или модуль отсутствует именно в этой версии Python.
Сначала прочитайте имя в кавычках в последней строке traceback. Затем проверьте интерпретатор и поиск модуля. Устанавливать пакет стоит только после того, как вы выяснили его настоящее имя и убедились, что он нужен проекту. Примеры ниже проверены на CPython 3.14.5.
Пакет ищет тот Python, который запущен
Сначала прочитайте точное имя модуля
Важна последняя строка, а не только первый импорт в вашем файле:
Traceback (most recent call last):
File "main.py", line 1, in <module>
import report_tool
File "/project/report_tool.py", line 3, in <module>
import openpyxl
ModuleNotFoundError: No module named 'openpyxl'
Программа нашла report_tool, открыла его и остановилась на внутреннем импорте openpyxl. Проверять нужно openpyxl. Если сообщение содержит No module named 'app.settings', Python не нашёл подмодуль settings внутри app; установка пакета с именем app.settings здесь не следует из ошибки.
Не путайте эту ошибку с ImportError: cannot import name. Во втором случае модуль найден, но в нём нет запрошенного имени: причина обычно в версии API, циклическом импорте или неверном имени объекта, а не в отсутствующей установке.
Проверьте, какой Python запускает программу
Так бывает, когда пакет установлен в системный Python, а редактор или терминал запускает Python из другой .venv. Узнайте путь к интерпретатору той же командой, которой запускаете проект:
python -c "import sys; print(sys.executable)"
python -m pip --version
Первая команда печатает исполняемый файл Python. Вторая показывает путь к pip и версию Python, к которой он относится. Оба пути должны вести в одно окружение. Например:
/project/.venv/bin/python
pip 25.1.1 from /project/.venv/lib/python3.14/site-packages/pip (python 3.14)
Теперь проверьте известное имя устанавливаемого дистрибутива:
python -m pip show Pillow
Location в выводе должен принадлежать той же .venv. Если pip show пишет Package(s) not found, это доказывает только одно: дистрибутив с таким именем не установлен для выбранного Python. Команда ничего не говорит о похожих именах и не подтверждает, что вы выбрали правильный пакет.
Используйте python -m pip, а не отдельную команду pip: модуль pip тогда запускает именно тот python, который стоит слева. Создание и активация окружения разобраны в инструкции по venv. Если проект управляет зависимостями через uv, запускайте его по сценарию с uv add и uv run, не смешивая два окружения.
Проверьте модуль без запуска приложения
importlib.util.find_spec() показывает, сможет ли текущий интерпретатор найти модуль:
python -c "import importlib.util; print(importlib.util.find_spec('PIL'))"
Для найденного модуля команда вернёт ModuleSpec с путём, например:
ModuleSpec(name='PIL', loader=..., origin='/project/.venv/lib/python3.14/site-packages/PIL/__init__.py', ...)
None означает, что обычный механизм импорта не видит PIL в этом окружении. Для верхнеуровневого имени такая проверка не выполняет код самого модуля, поэтому удобна до пробного импорта. После успешного find_spec узнайте, какой файл загрузился на самом деле:
python -c "import PIL; print(PIL.__file__)"
Путь может обнаружить другую проблему: например, локальный PIL.py затенил установленную библиотеку. Переименуйте такой файл и повторите проверку.
Имя на PyPI может не совпадать с именем в import
В import PIL указано имя импортируемого пакета. В python -m pip install Pillow указано имя дистрибутива. PyPA приводит эту пару как официальный пример несовпадения. Другой дистрибутив может экспортировать несколько импортируемых пакетов, а одно импортируемое имя могут предоставлять разные дистрибутивы.
Поэтому не подставляйте текст ошибки в pip install автоматически. Пакет с совпадающим именем на PyPI может оказаться чужим, заброшенным или вредоносным. Найдите имя зависимости в pyproject.toml, requirements.txt или документации проекта; для сторонней библиотеки проверьте официальный сайт, репозиторий и страницу издателя на PyPI. Если источник зависимости неизвестен, остановитесь и уточните его, а не перебирайте похожие пакеты.
Когда зависимость подтверждена, восстановите окружение из файла проекта:
python -m pip install -r requirements.txt
Для проекта с pyproject.toml, который устанавливается как пакет, команда может быть такой:
python -m pip install -e .
Режим -e полезен в разработке: пакет остаётся связан с исходниками. Не применяйте эти команды наугад — выберите ту, которую предусматривает сам проект.
Локальный пакет: рабочая директория и package root
Допустим, проект устроен так:
shop-project/
├── pyproject.toml
└── shop_app/
├── __init__.py
├── cli.py
└── prices.py
В cli.py используется абсолютный импорт:
from shop_app.prices import load_prices
Запускайте модуль из корня shop-project, то есть из каталога, который содержит пакет shop_app:
cd shop-project
python -m shop_app.cli
Прямой запуск python shop_app/cli.py меняет начальную точку поиска: первой становится директория shop_app, а её родительский каталог может не попасть туда, где ожидается package root. Запуск через -m сохраняет пакетный контекст и позволяет абсолютному импорту найти shop_app.
Проверьте текущую директорию и весь путь поиска одной командой:
python -c "import os, sys; print('cwd:', os.getcwd()); print(*sys.path, sep='\n')"
Python формирует sys.path при старте. Для файла в начале обычно стоит каталог этого файла, а для python -m, python -c и интерактивного запуска — текущая директория. Затем добавляются пути стандартной библиотеки, окружения и site-packages. Если каталог над shop_app отсутствует, исправьте команду запуска, установите проект в окружение или перейдите в package root.
Почему не стоит дописывать sys.path в коде
Такой фрагмент часто скрывает ошибку запуска:
import sys
sys.path.insert(0, '/home/user/shop-project')
Жёсткий путь работает только на одной машине. Относительный путь зависит от текущей директории, меняет приоритет модулей и может незаметно подхватить одноимённый файл не из того места. В тестах, редакторе и продакшене список путей снова различится.
Постоянный фикс — корректная структура пакета и одна воспроизводимая команда запуска: python -m shop_app.cli, python -m pip install -e . либо установка зависимостей проекта в его .venv. Ручное изменение sys.path оправдано в редких загрузчиках и одноразовой диагностике, но не как обычная настройка приложения.
Проверьте опечатку, регистр и версию Python
Импортируемые имена чувствительны к регистру. import Requests и import requests — разные имена; на файловой системе без учёта регистра ошибка может временно не проявиться и сломать запуск на Linux. Сверьте каждую часть имени с документацией и именем файла: user_profile.py импортируется как user_profile, а не user-profile.
Модуль стандартной библиотеки тоже зависит от версии Python. Например, tomllib появился в Python 3.11, а несколько устаревших модулей, включая imghdr, удалены в Python 3.13. Проверьте фактическую версию и официальный индекс модулей для неё:
python --version
python -c "import importlib.util; print(importlib.util.find_spec('tomllib'))"
Если код рассчитан на другую версию, выберите поддерживаемый интерпретатор или предусмотренную проектом замену. Не пытайтесь «вернуть» стандартный модуль установкой случайного одноимённого дистрибутива из PyPI.
Симптом, проверка и исправление
| Симптом | Что проверить | Что исправить |
|---|---|---|
No module named 'requests', хотя установка уже была | sys.executable, python -m pip --version | Выбрать одну .venv и запускать pip через тот же Python |
python -m pip show Pillow находит пакет, а import PIL падает | find_spec('PIL'), поле Location | Убрать смешение окружений или восстановить установку по файлу зависимостей |
Имя после No module named не совпадает с первым импортом | Последние строки traceback | Исправить или установить именно вложенную зависимость, подтверждённую проектом |
Имя из import не находится на PyPI или выглядит подозрительно | pyproject.toml, документацию и официальный репозиторий | Найти настоящее имя дистрибутива; не ставить пакет по догадке |
| Локальный пакет находится в репозитории, но не импортируется | cwd, sys.path, каталог над пакетом | Запустить из package root через python -m или установить проект с -e . |
| Ошибка появляется только на Linux или в CI | Регистр букв в импорте и имени файла | Привести написание к точному имени модуля |
| Стандартный модуль есть в документации, но не в окружении | python --version, индекс модулей этой версии | Использовать совместимую версию Python или документированную замену |
find_spec показывает неожиданный файл проекта | Имя локального .py-файла | Переименовать файл, который затеняет нужный пакет |
Короткий порядок диагностики
- Прочитайте точное имя после
No module namedи последний импорт в traceback. - Сравните
sys.executableс путём изpython -m pip --version. - Для подтверждённого дистрибутива выполните
python -m pip show <имя>. - Проверьте импортируемое имя через
importlib.util.find_spec(). - Для локального пакета проверьте
cwd,sys.path, package root и запуск черезpython -m. - Только после этого устанавливайте объявленную зависимость или исправляйте структуру проекта.
Если программа после исправления импорта падает уже внутри try, обработку таких сбоев стоит строить через конкретные исключения. Базовые схемы собраны в статье «try/except в Python».