- Решение проблем с модулями и пакетами Python
- Отсутствие модуля Python
- Пакет Python установлен, но программа его не видит
- Установлена новая версия модуля, но программа видит старую версию
- Ошибки с фразой «AttributeError: ‘NoneType’ object has no attribute»
- Модуль установлен, но при обновлении или обращении к нему появляется ошибки
- Заключение
- Python — Error Types
- IndexError
- ModuleNotFoundError
- KeyError
- ImportError
- StopIteration
- TypeError
- ValueError
- NameError
- ZeroDivisionError
- KeyboardInterrupt
Решение проблем с модулями и пакетами Python
Я с завидной регулярностью сталкиваюсь со всевозможными ошибками, так или иначе связанными с модулями Python. Существует огромное количество разнообразных модулей Python, которые разработчики активно используют, но далеко не всегда заботятся об установке зависимостей. Некоторые даже не удосуживаются их документировать. Параллельно существует две мажорные версии Python: 2 и 3. В разных дистрибутивах отдано предпочтение одной или другой версии, по этой причине самостоятельно установленную программу в зависимости от дистрибутива нужно при запуске предварять python или python2/python3. Например:
Причём обычно не происходит никаких проверок и угадали ли вы с выбором версии или нет вы узнаете только при появлении первых ошибок, вызванных неправильным синтаксисом программного кода для данной версии.
Также прибавляет путаницу то, что модули можно установить как из стандартного репозитория дистрибутивов, так и с помощью pip (инструмент для установки пакетов Python).
Цель этой заметки — рассмотреть некоторые характерные проблемы модулей Python. Все возможные ошибки вряд ли удастся охватить, но описанное здесь должно помочь понять, в каком примерно направлении двигаться.
Отсутствие модуля Python
Большинство ошибок модулей Python начинаются со строк:
Exception: Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/………. ……………… ………………
В них трудно разобраться, поэтому поищите фразы вида:
- ModuleNotFoundError: No module named
- No module named
- ImportError: No module named
За ними следует название модуля.
Поищите по указанному имени в системном репозитории, или попробуйте установить командой вида:
Пакет Python установлен, но программа его не видит
Причина может быть в том, что вы установили модуль для другой версии. Например, программа написана на Python3, а вы установили модуль с этим же названием, но написанный на Python2. В этом случае он не будет существовать для программы. Поэтому нужно правильно указывать номер версии.
Команда pip также имеет свои две версии: pip2 и pip3. Если версия не указана, то это означает, что используется какая-то из двух указанных (2 или 3) версий, которая является основной в системе. Например, сейчас в Debian и производных по умолчанию основной версией Python является вторая. Поэтому в репозитории есть два пакета: python-pip (вторая версия) и python3-pip (третья).
В Arch Linux и производных по умолчанию основной версией является третья, поэтому в репозиториях присутствует пакет python-pip (третья версия) и python2-pip (вторая).
Это же самое относится к пакетам Python и самому Python: если версия не указана, значит имеется ввиду основная для вашего дистрибутива версия. По этой причине многие пакеты в репозитории присутствуют с двумя очень похожими названиями.
Установлена новая версия модуля, но программа видит старую версию
Я несколько раз сталкивался с подобными необъяснимыми ошибками.
Иногда помогает удаление модуля командой вида:
sudo pip2 uninstall модуль
Также попробуйте удалить его используя системный менеджер пакетов.
Если модуль вам нужен, попробуйте вновь установить его и проверьте, решило ли это проблему.
Если проблема не решена, то удалите все файлы модуля, обычно они расположены в папках вида:
Ошибки с фразой «AttributeError: ‘NoneType’ object has no attribute»
Ошибки, в которых присутствует слово AttributeError, NoneType, object has no attribute обычно вызваны не отсутствием модуля, а тем, что модуль не получил ожидаемого аргумента, либо получил неправильное число аргументов. Было бы правильнее сказать, что ошибка вызвана недостаточной проверкой данных и отсутствием перехвата исключений (то есть программа плохо написана).
В этих случаях обычно ничего не требуется дополнительно устанавливать. В моей практике частыми случаями таких ошибок является обращение программы к определённому сайту, но сайт может быть недоступен, либо API ключ больше недействителен, либо программа не получила ожидаемые данные по другим причинам. Также программа может обращаться к другой программе, но из-за ошибки в ней получит не тот результат, который ожидала, и уже это вызывает приведённые выше ошибки, которые мы видим.
Опять же, хорошо написанная программа в этом случае должна вернуть что-то вроде «информация не загружена», «работа программы N завершилась ошибкой» и так далее. Как правило, нужно разбираться с причиной самой первой проблемы или обращаться к разработчику.
Модуль установлен, но при обновлении или обращении к нему появляется ошибки
Это самая экзотическая ошибка, которая вызвана, видимо, повреждением файлов пакета. К примеру, при попытке обновления я получал ошибку:
Requirement already satisfied: networkx in /usr/lib/python2.7/site-packages (2.1) Exception: Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/pip/_internal/basecommand.py", line 141, in main status = self.run(options, args) File "/usr/lib/python2.7/site-packages/pip/_internal/commands/install.py", line 299, in run resolver.resolve(requirement_set) File "/usr/lib/python2.7/site-packages/pip/_internal/resolve.py", line 102, in resolve self._resolve_one(requirement_set, req) File "/usr/lib/python2.7/site-packages/pip/_internal/resolve.py", line 261, in _resolve_one check_dist_requires_python(dist) File "/usr/lib/python2.7/site-packages/pip/_internal/utils/packaging.py", line 46, in check_dist_requires_python feed_parser.feed(metadata) File "/usr/lib/python2.7/email/feedparser.py", line 177, in feed self._input.push(data) File "/usr/lib/python2.7/email/feedparser.py", line 99, in push parts = data.splitlines(True) AttributeError: 'NoneType' object has no attribute 'splitlines'
При этом сам модуль установлен как следует из самой первой строки.
Проблема может решиться удалением всех файлов пакета (с помощью rm) и затем повторной установки.
К примеру в рассматриваемом случае, удаление:
rm -rf /usr/lib/python2.7/site-packages/networkx-2.1-py2.7.egg-info/
pip2 install networkx Collecting networkx Downloading https://files.pythonhosted.org/packages/11/42/f951cc6838a4dff6ce57211c4d7f8444809ccbe2134179950301e5c4c83c/networkx-2.1.zip (1.6MB) 100% |████████████████████████████████| 1.6MB 2.9MB/s Requirement already satisfied: decorator>=4.1.0 in /usr/lib/python2.7/site-packages (from networkx) (4.3.0) Installing collected packages: networkx Running setup.py install for networkx . done Successfully installed networkx-2.1
После этого проблема с модулем исчезла.
Заключение
Пожалуй, это далеко не полный «справочник ошибок Python», но если вы можете сориентироваться, какого рода ошибка у вас возникла:
- отсутствует модуль
- модуль неправильной версии
- модуль повреждён
- внешняя причина — программа не получила ожидаемые данные
Так вот, если вы хотя бы примерно поняли главную причину, то вам будет проще понять, в каком направлении двигаться для её решения.
Python — Error Types
The most common reason of an error in a Python program is when a certain statement is not in accordance with the prescribed usage. Such an error is called a syntax error. The Python interpreter immediately reports it, usually along with the reason.
>>> print "hello" SyntaxError: Missing parentheses in call to 'print'. Did you mean print("hello")?
In Python 3.x, print is a built-in function and requires parentheses. The statement above violates this usage and hence syntax error is displayed.
Many times though, a program results in an error after it is run even if it doesn’t have any syntax error. Such an error is a runtime error, called an exception. A number of built-in exceptions are defined in the Python library. Let’s see some common error types.
The following table lists important built-in exceptions in Python.
Exception | Description |
---|---|
AssertionError | Raised when the assert statement fails. |
AttributeError | Raised on the attribute assignment or reference fails. |
EOFError | Raised when the input() function hits the end-of-file condition. |
FloatingPointError | Raised when a floating point operation fails. |
GeneratorExit | Raised when a generator’s close() method is called. |
ImportError | Raised when the imported module is not found. |
IndexError | Raised when the index of a sequence is out of range. |
KeyError | Raised when a key is not found in a dictionary. |
KeyboardInterrupt | Raised when the user hits the interrupt key (Ctrl+c or delete). |
MemoryError | Raised when an operation runs out of memory. |
NameError | Raised when a variable is not found in the local or global scope. |
NotImplementedError | Raised by abstract methods. |
OSError | Raised when a system operation causes a system-related error. |
OverflowError | Raised when the result of an arithmetic operation is too large to be represented. |
ReferenceError | Raised when a weak reference proxy is used to access a garbage collected referent. |
RuntimeError | Raised when an error does not fall under any other category. |
StopIteration | Raised by the next() function to indicate that there is no further item to be returned by the iterator. |
SyntaxError | Raised by the parser when a syntax error is encountered. |
IndentationError | Raised when there is an incorrect indentation. |
TabError | Raised when the indentation consists of inconsistent tabs and spaces. |
SystemError | Raised when the interpreter detects internal error. |
SystemExit | Raised by the sys.exit() function. |
TypeError | Raised when a function or operation is applied to an object of an incorrect type. |
UnboundLocalError | Raised when a reference is made to a local variable in a function or method, but no value has been bound to that variable. |
UnicodeError | Raised when a Unicode-related encoding or decoding error occurs. |
UnicodeEncodeError | Raised when a Unicode-related error occurs during encoding. |
UnicodeDecodeError | Raised when a Unicode-related error occurs during decoding. |
UnicodeTranslateError | Raised when a Unicode-related error occurs during translation. |
ValueError | Raised when a function gets an argument of correct type but improper value. |
ZeroDivisionError | Raised when the second operand of a division or module operation is zero. |
IndexError
The IndexError is thrown when trying to access an item at an invalid index.
>>> L1=[1,2,3] >>> L1[3] Traceback (most recent call last): File "", line 1, in L1[3] IndexError: list index out of range
ModuleNotFoundError
The ModuleNotFoundError is thrown when a module could not be found.
>>> import notamodule Traceback (most recent call last): File "", line 1, in import notamodule ModuleNotFoundError: No module named 'notamodule'
KeyError
The KeyError is thrown when a key is not found.
>>> D1= >>> D1['4'] Traceback (most recent call last): File "", line 1, in D1['4'] KeyError: '4'
ImportError
The ImportError is thrown when a specified function can not be found.
>>> from math import cube Traceback (most recent call last): File "", line 1, in from math import cube ImportError: cannot import name 'cube'
StopIteration
The StopIteration is thrown when the next() function goes beyond the iterator items.
>>> it=iter([1,2,3]) >>> next(it) 1 >>> next(it) 2 >>> next(it) 3 >>> next(it) Traceback (most recent call last): File "", line 1, in next(it) StopIteration
TypeError
The TypeError is thrown when an operation or function is applied to an object of an inappropriate type.
>>> '2'+2 Traceback (most recent call last): File "", line 1, in '2'+2 TypeError: must be str, not int
ValueError
The ValueError is thrown when a function’s argument is of an inappropriate type.
>>> int('xyz') Traceback (most recent call last): File "", line 1, in int('xyz') ValueError: invalid literal for int() with base 10: 'xyz'
NameError
The NameError is thrown when an object could not be found.
>>> age Traceback (most recent call last): File "", line 1, in age NameError: name 'age' is not defined
ZeroDivisionError
The ZeroDivisionError is thrown when the second operator in the division is zero.
>>> x=100/0 Traceback (most recent call last): File "", line 1, in x=100/0 ZeroDivisionError: division by zero
KeyboardInterrupt
The KeyboardInterrupt is thrown when the user hits the interrupt key (normally Control-C) during the execution of the program.
>>> name=input('enter your name') enter your name^c Traceback (most recent call last): File "", line 1, in name=input('enter your name') KeyboardInterrupt
Learn how to handle exceptions in Python in the next chapter.