ImportError в Python: причины и решения
Почему Python выдаёт ImportError и как это исправить: cannot import name, циклический импорт, relative import, DLL load failed, затенение и версии библиотек.
Содержание · 12 разделов
- Как определить причину по тексту ошибки
- Cannot import name: имени нет в модуле
- Опечатка или имя спрятано внутри класса
- Имя удалено или переименовано в новой версии
- Версия слишком старая
- Установлен не тот пакет с тем же именем модуля
- Циклический импорт: partially initialized module
- Как разорвать цикл
- Ваш файл или папка затеняет модуль
- Attempted relative import with no known parent package
- DLL load failed в Windows
- Несовместимые версии бинарных пакетов
- ImportError, который подняла сама библиотека
- Как обработать ImportError в коде
- Чек-лист: что проверить при ImportError
- Частые вопросы
- Обновил пакет, а ImportError остался — почему?
- Как найти все циклические импорты в проекте?
- Локально всё работает, а на сервере или в Docker — ImportError. Что не так?
- Помогает ли удаление __pycache__?
- Чем ImportError отличается от AttributeError при импорте?
- Итог
ImportError в Python означает, что модуль найти удалось, а импортировать — нет: в модуле нет нужного имени (cannot import name), модули импортируют друг друга по кругу, относительный импорт запущен без пакета или не загрузилась бинарная библиотека (DLL load failed). Причину почти всегда видно по тексту после двоеточия в последней строке traceback.
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: cannot import name 'pathx' from 'os' (C:\Python312\Lib\os.py). Did you mean: 'path'?
Если в сообщении написано No module named '…', это другой случай — ModuleNotFoundError, подкласс ImportError: Python не нашёл сам модуль. Его решения (установить пакет, выбрать правильный интерпретатор) собраны в статье ModuleNotFoundError: No module named. Ниже — всё остальное.
Как определить причину по тексту ошибки
Сообщения ниже получены в Python 3.12 и 3.14.
| Текст в конце traceback | Что произошло | Раздел |
|---|---|---|
cannot import name 'x' from 'mod' (путь) | В модуле нет имени x: опечатка, другая версия библиотеки, не тот пакет | cannot import name |
... from partially initialized module 'mod' (most likely due to a circular import) | Модули импортируют друг друга | Циклический импорт |
... (consider renaming '…' since it has the same name as …) | Ваш файл назван как стандартный модуль или библиотека (Python 3.13+) | Затенение, циклический импорт |
cannot import name 'x' from 'mod' (unknown location) | Вместо пакета импортирована папка без __init__.py; у встроенных модулей — просто опечатка | Затенение |
attempted relative import with no known parent package | Файл с from .x import y запущен напрямую | Относительный импорт |
DLL load failed while importing mod | Windows не нашла DLL, нужную бинарному модулю | DLL load failed |
Couldn't import Django..., ... Use pip or conda to install ... | Ошибку подняла сама библиотека и описала причину | ImportError из библиотеки |
В Python 3.12 и новее для опечаток добавляется подсказка Did you mean: '…'?. В скобках после имени модуля Python печатает путь к файлу, из которого модуль загружен, — по нему видно, какой именно os или django импортировался.
Cannot import name: имени нет в модуле
Запись from модуль import имя выполняется в два этапа: сначала Python загружает модуль, затем ищет в нём атрибут с указанным именем. Если модуль загрузился, а атрибута нет, возникает ImportError: cannot import name.
Опечатка или имя спрятано внутри класса
Начните с простого: сверьте имя с документацией, включая регистр. Python 3.12+ подсказывает похожее имя:
>>> from math import sqr
ImportError: cannot import name 'sqr' from 'math' (unknown location). Did you mean: 'sqrt'?
Для встроенных модулей вроде math путь заменяется на (unknown location) — у них нет файла .py.
Импортировать можно только имена верхнего уровня модуля: функции, классы и переменные, объявленные вне других блоков. Метод класса так не импортируется:
# fn.py
class Answer:
def hey(self):
return "hello"
>>> from fn import hey
ImportError: cannot import name 'hey' from 'fn' (C:\projects\bot\fn.py)
Импортируйте класс (from fn import Answer) и вызывайте метод у объекта: Answer().hey(). То же касается имён, созданных внутри функции или блока if __name__ == "__main__":.
Имя удалено или переименовано в новой версии
Самая частая причина в чужом коде: пример из старого учебника или Stack Overflow написан для прошлой версии библиотеки, а у вас установлена новая. Несколько реальных примеров:
| Импорт | Ошибка возникает | Как теперь |
|---|---|---|
from collections import Mapping | Python 3.10+ | from collections.abc import Mapping |
from urllib import urlencode | любой Python 3 (это код для Python 2) | from urllib.parse import urlencode |
from django.utils.encoding import force_text | Django 4.0+ | from django.utils.encoding import force_str |
from django.conf.urls import url | Django 4.0+ | from django.urls import re_path (или path) |
from pydantic import BaseSettings | Pydantic 2 | pip install pydantic-settings, затем from pydantic_settings import BaseSettings |
Например, в проекте на Django 5.2 старый код падает так:
ImportError: cannot import name 'force_text' from 'django.utils.encoding' (C:\projects\shop\.venv\Lib\site-packages\django\utils\encoding.py). Did you mean: 'force_bytes'?
Подсказка Did you mean здесь ведёт не туда: force_bytes — другая функция. Замену ищите в журнале изменений (release notes) библиотеки по имени из ошибки. Некоторые библиотеки сами объясняют переезд. Pydantic 2 поднимает собственный подкласс ImportError:
pydantic.errors.PydanticImportError: `BaseSettings` has been moved to the `pydantic-settings` package. See https://pydantic.dev/docs/validation/2.14/migration/#basesettings-has-moved-to-pydantic-settings for more details.
Подробнее о второй версии библиотеки — в статье Pydantic в Python.
Сначала узнайте, какая версия установлена и откуда загружается модуль:
python -m pip show django # строки Version и Location
python -c "import django; print(django.__version__, django.__file__)"
5.2.18 C:\projects\shop\.venv\Lib\site-packages\django\__init__.py
Дальше два пути:
- обновить код под установленную версию — правильный вариант для живого проекта;
- поставить версию, под которую написан код, например
python -m pip install "django<4", — допустимо для старого проекта, который вы не собираетесь развивать. Учтите, что старые версии не получают исправлений безопасности.
Версия слишком старая
Бывает и наоборот: имя появилось в библиотеке или в Python позже вашей версии. Декоратор typing.override добавлен в Python 3.12, поэтому в 3.11 импорт падает:
ImportError: cannot import name 'override' from 'typing' (C:\Python311\Lib\typing.py)
Обновите Python или библиотеку. Для новых возможностей typing есть пакет-бэкпорт typing_extensions: from typing_extensions import override работает и в старых версиях.
Установлен не тот пакет с тем же именем модуля
Разные пакеты на PyPI могут давать модуль с одинаковым именем. Классический пример — jwt: команда pip install jwt ставит не ту библиотеку, что описана в большинстве руководств.
ImportError: cannot import name 'encode' from 'jwt' (C:\projects\api\.venv\Lib\site-packages\jwt\__init__.py)
Нужный пакет называется PyJWT:
python -m pip uninstall jwt
python -m pip install PyJWT
Если пути в ошибке и в pip show указывают на одну папку, а имени всё равно нет, проверьте страницу пакета на pypi.org: возможно, ставили одноимённый проект другого автора.
Циклический импорт: partially initialized module
Циклический импорт возникает, когда модуль A импортирует модуль B, а B — снова A. Возьмём два модуля интернет-магазина:
# orders.py
from users import User
class Order:
def __init__(self, customer: User, total: int):
self.customer = customer
self.total = total
# users.py
from orders import Order
class User:
def __init__(self, name: str):
self.name = name
self.orders: list[Order] = []
C:\projects\shop> python main.py
Traceback (most recent call last):
File "C:\projects\shop\main.py", line 1, in <module>
from orders import Order
File "C:\projects\shop\orders.py", line 1, in <module>
from users import User
File "C:\projects\shop\users.py", line 1, in <module>
from orders import Order
ImportError: cannot import name 'Order' from partially initialized module 'orders' (most likely due to a circular import) (C:\projects\shop\orders.py)
Python выполняет модуль сверху вниз. orders.py начинает загружаться, на первой строке уходит в users.py, а тот просит Order из orders, где выполнение ещё не дошло до объявления класса. Модуль «частично инициализирован» (partially initialized): он уже есть в sys.modules, но Order в нём пока нет. Traceback показывает весь круг — читайте строки File сверху вниз.
Важно: в Python 3.14 тот же круг из модулей, лежащих рядом с запускаемым скриптом, выводится с другой подсказкой:
cannot import name 'Order' from 'orders' (consider renaming '…\orders.py' if it has the same name as a library you intended to import). Если библиотеки с таким именем у вас нет, ищите циклический импорт. Для модулей внутри пакета (shop.orders) сообщение остаётся прежним — про partially initialized module.
Как разорвать цикл
Способы перечислены от самого чистого к компромиссному:
-
Вынести общий код в третий модуль. Если двум модулям нужны одни и те же классы или функции, перенесите их в отдельный модуль (
models.py,common.py), который ни от кого не зависит. -
Импортировать для аннотаций только при проверке типов. Если имя нужно лишь в аннотациях типов, импорт можно убрать из выполнения:
# users.py from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from orders import Order class User: def __init__(self, name: str): self.name = name self.orders: list[Order] = []TYPE_CHECKINGравенFalseпри запуске иTrueдля анализаторов вроде mypy, поэтому импорт видят только они. Строкаfrom __future__ import annotationsоткладывает вычисление аннотаций; в Python 3.14 это поведение включено по умолчанию. -
Импортировать модуль целиком.
import ordersвместоfrom orders import Order, а обращениеorders.Order— внутри функций. Имя ищется в момент вызова, когда оба модуля уже загружены. -
Перенести импорт внутрь функции. Самый быстрый, но менее читаемый способ:
# users.py class User: def __init__(self, name: str): self.name = name def make_order(self, total: int): from orders import Order # импорт в момент вызова, а не при загрузке return Order(self, total)
В Django циклы чаще всего возникают между models.py разных приложений. Для связей импорт не нужен: укажите модель строкой, models.ForeignKey("users.User", on_delete=models.CASCADE), — Django найдёт её после загрузки всех приложений. Подробнее — в статье о ForeignKey в Django.
В Python 3.15 появились ленивые импорты: строка lazy from orders import Order откладывает загрузку модуля до первого обращения к имени, и такой цикл на уровне модулей не мешает запуску.
Ваш файл или папка затеняет модуль
Python ищет модули в папках из sys.path, и первой идёт папка запускаемого скрипта. Если в ней лежит random.py, json.py, requests.py или telegram/, импорт найдёт их раньше настоящей библиотеки. Скрипт random.py с первой строкой from random import randint в Python 3.12 импортирует сам себя:
ImportError: cannot import name 'randint' from partially initialized module 'random' (most likely due to a circular import) (C:\projects\dice\random.py)
Начиная с Python 3.13 сообщение называет причину прямо:
ImportError: cannot import name 'randint' from 'random' (consider renaming 'C:\\projects\\dice\\random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)
Если файл импортируется из другого скрипта, в Python 3.12 нет даже упоминания цикла — только путь в скобках:
ImportError: cannot import name 'dumps' from 'json' (C:\projects\dice\json.py)
Путь ведёт в папку проекта вместо Lib или site-packages — это и есть признак затенения. Переименуйте файл (dice_random.py, my_json.py). Удалять __pycache__ после переименования не нужно: скомпилированный кэш без исходного файла Python не использует.
Модули, встроенные в сам интерпретатор, затенить файлом нельзя: они загружаются раньше поиска по папкам. Это всегда sys и builtins, а в сборке для Windows ещё и math, time и другие. Список для вашей установки — в sys.builtin_module_names.
Похожая ловушка — папка без __init__.py с именем пакета, которого нет в окружении. Python считает её пакетом пространства имён (namespace package), и вместо ModuleNotFoundError появляется загадочное:
ImportError: cannot import name 'Update' from 'telegram' (unknown location)
Переименуйте папку и установите нужный пакет. Если файл затеняет модуль при import random и последующем вызове random.randint(), ошибка будет уже другой — AttributeError: partially initialized module, она разобрана в статье AttributeError в Python.
Attempted relative import with no known parent package
Относительный импорт с точкой (from .utils import slugify) работает только внутри пакета: точка означает «пакет, в котором лежит этот модуль». Когда файл запускают напрямую, он становится модулем __main__ без родительского пакета, и Python не понимает, от чего отсчитывать точку.
shop/
├── __init__.py
├── main.py # from .utils import slugify
├── utils.py
└── services/
├── __init__.py
└── catalog.py # from ..utils import slugify
C:\projects> python shop\main.py
Traceback (most recent call last):
File "C:\projects\shop\main.py", line 1, in <module>
from .utils import slugify
ImportError: attempted relative import with no known parent package
Запустите модуль через -m из папки, где лежит пакет. Путь пишется через точки, без .py:
C:\projects> python -m shop.main
hello-world
C:\projects> python -m shop.services.catalog
hello-world
На macOS и Linux команды те же, только с python3 и прямыми слешами в путях. Запуск -m из неправильной папки даёт вариации ошибки. Из shop команда python -m main выдаст ту же no known parent package, а python -m services.catalog — attempted relative import beyond top-level package: две точки ведут выше пакета services, который Python считает верхним.
Другие варианты:
- заменить относительный импорт абсолютным (
from shop.utils import slugify) и запускать из корня проекта; - в PyCharm в конфигурации запуска выбрать Module name вместо Script path; в VS Code — конфигурацию отладки с
"module": "shop.main"вlaunch.json.
Как Python заполняет sys.path при разных способах запуска, разобрано в статье как запустить Python-скрипт.
DLL load failed в Windows
Бинарные модули (файлы .pyd в numpy, pandas, opencv-python, PyQt, torch) загружаются через системный загрузчик Windows. Если не хватает DLL, от которой зависит модуль, Python сообщает:
ImportError: DLL load failed while importing _sqlite3: The specified module could not be found.
В русской Windows конец сообщения звучит как «Не найден указанный модуль.» Имя после while importing — модуль, который не загрузился. Отсутствующую DLL Python не называет.
Частые причины и решения:
- Нет Microsoft Visual C++ Redistributable. Многие пакеты собраны компилятором MSVC и требуют его библиотеки времени выполнения. Установите актуальный пакет Visual C++ Redistributable x64 с сайта Microsoft.
- Повреждённая или смешанная установка. Пакет обновился не полностью или его части поставили разные менеджеры (pip и conda). Переустановите:
python -m pip install --force-reinstall имя_пакета. - Не активировано окружение conda. DLL пакетов conda лежат в папке окружения и находятся только после
conda activate. Это касается и IDE: выберите интерпретатор окружения в настройках. - Windows N или KN. В этих редакциях нет Media Feature Pack, который нужен OpenCV. Установите его в компонентах Windows.
- Несовпадение разрядности. 32-битный Python не загрузит 64-битную DLL и наоборот. Проверьте:
python -c "import struct; print(struct.calcsize('P') * 8)"выводит64или32.
С Python 3.8 зависимости бинарных модулей не ищутся в PATH и текущей папке — только в системных каталогах, в папке самого .pyd и в каталогах, добавленных через os.add_dll_directory(). Поэтому совет «добавьте папку в PATH» для импорта больше не работает. Если DLL лежат в отдельной папке, добавьте её в коде до импорта:
import os
os.add_dll_directory(r"C:\libs\sqlite")
import _sqlite3
Найти, какой именно DLL не хватает, поможет бесплатная утилита Dependencies: откройте в ней проблемный .pyd из site-packages, отсутствующие библиотеки будут подсвечены.
В Linux та же проблема выглядит как ImportError: libGL.so.1: cannot open shared object file: No such file or directory — обычно у OpenCV в Docker-контейнере. Для серверов без графического интерфейса ставьте opencv-python-headless вместо opencv-python.
Несовместимые версии бинарных пакетов
Пакеты с C-расширениями собираются под конкретную версию NumPy. После обновления NumPy до 2.x старые pandas, matplotlib или scikit-learn перестают импортироваться. NumPy предупреждает сообщением A module that was compiled using NumPy 1.x cannot be run in NumPy 2.0.0 as it may crash (с вашей версией вместо 2.0.0), за которым следует ImportError или AttributeError: _ARRAY_API not found. У пакетов на Cython та же проблема выглядит как ValueError:
ValueError: numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject
Найдите в traceback первый снизу файл не из папки numpy — это пакет, который нужно обновить: python -m pip install --upgrade pandas. Если новой версии нет, верните NumPy первой ветки: python -m pip install "numpy<2". Чтобы на сервере не получилась другая комбинация версий, фиксируйте их в requirements.txt.
ImportError, который подняла сама библиотека
Иногда ImportError поднимает код самой библиотеки и в тексте сразу пишет, что делать. Запуск manage.py без активированного окружения:
ModuleNotFoundError: No module named 'django'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
...
ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?
Здесь два исключения в цепочке: исходное — ModuleNotFoundError, поэтому решение то же, что для No module named: активировать окружение проекта или установить Django.
pandas так сообщает о необязательной зависимости, нужной только для части функций:
ImportError: `Import tabulate` failed. Use pip or conda to install the tabulate package.
Установите названный пакет (python -m pip install tabulate) — сам pandas переустанавливать не нужно.
Как обработать ImportError в коде
Перехват ошибки импорта уместен для необязательных зависимостей: если быстрая библиотека установлена — используем её, если нет — стандартную.
try:
import orjson as json_impl
except ModuleNotFoundError:
import json as json_impl
print(json_impl.__name__) # → json, если orjson не установлен
Ловите только ModuleNotFoundError: перехват всего ImportError скроет настоящую поломку — циклический импорт, DLL load failed или ошибку внутри установленного модуля. У исключения есть атрибуты name (имя модуля) и path (путь к файлу), они пригодятся в логах:
try:
from os import pathx
except ImportError as error:
print(error.name) # → os
print(error.path) # → C:\Python312\Lib\os.py
Общие правила try/except — в статье обработка исключений в Python.
Чек-лист: что проверить при ImportError
- Прочитайте последнюю строку traceback и найдите свой вариант в таблице в начале статьи.
- Посмотрите путь в скобках: модуль загружен из
site-packagesили из папки проекта. - Для
cannot import nameпроверьте написание имени и версию пакета (python -m pip show имя). - Если в сообщении есть
partially initializedилиconsider renaming, ищите цикл между модулями или файл с именем библиотеки. - Для относительных импортов запускайте код через
python -m пакет.модульиз корня проекта. - Для
DLL load failedустановите Visual C++ Redistributable и переустановите пакет в активированном окружении.
Частые вопросы
Обновил пакет, а ImportError остался — почему?
Работающий процесс уже загрузил старую версию модуля. Перезапустите сервер разработки, ядро Jupyter или IDE. Если не помогло, пакет обновился в другом интерпретаторе: сравните вывод python -c "import sys; print(sys.executable)" с интерпретатором проекта.
Как найти все циклические импорты в проекте?
Линтер pylint умеет проверять только их: python -m pylint --disable=all --enable=cyclic-import имя_пакета. Для каждого круга он выводит сообщение вида R0401: Cyclic import (shop.orders -> shop.users).
Локально всё работает, а на сервере или в Docker — ImportError. Что не так?
Почти всегда отличаются версии: на сервер приехала более новая библиотека, где имя удалено, или другая версия Python. Зафиксируйте точные версии в requirements.txt (python -m pip freeze). Для ошибок про .so-файлы в Linux проверьте, что в образе есть системные библиотеки, которые нужны пакету.
Помогает ли удаление __pycache__?
Редко. Python сверяет кэш с исходным файлом и перекомпилирует его при изменениях, а кэш удалённого или переименованного файла не использует. Удаление кэша не исправит ни опечатку, ни цикл, ни затенение.
Чем ImportError отличается от AttributeError при импорте?
from модуль import имя при отсутствии имени выдаёт ImportError. Запись import модуль с последующим модуль.имя выдаёт AttributeError — уже при обращении к атрибуту. Причины у них общие: опечатка, версия библиотеки, цикл или затенение.
Итог
ImportError означает, что модуль найден, но импорт не удался. Последняя строка traceback почти всегда указывает причину: cannot import name — имени нет в этой версии модуля или установлен не тот пакет; partially initialized — циклический импорт; consider renaming и путь в папку проекта — файл затеняет библиотеку; no known parent package — нужен запуск через python -m; DLL load failed — не хватает системной библиотеки. Как читать traceback целиком и разбирать другие исключения, рассказано в руководстве «Ошибки в Python: как читать traceback».
- #Python
- #ImportError
- #Импорт
- #Исключения
- #Отладка