Люди, которые только начинают программировать на Python, часто бывают ошеломлены, когда что-то идет не так, в основном потому, что переводчик Python выплевывает кучу сообщений на английском языке. В этой статье мы надеемся помочь вам привыкнуть к чтению ошибок, а решения обычно появляются сами собой, как только вы их поймете.
Грамматические ошибки
Самая распространенная ошибка для новичков — синтаксическая ошибка, когда вы пишете программу не в соответствии с правилами синтаксиса Python, и Python не работает. двоеточия и т.д.
Синтаксические ошибки в интерактивной среде
Начнем с примера строки, в которой отсутствует закрывающая кавычка, в интерактивной среде Python (разные версии Python могут отображать разные сообщения, в данной статье в качестве основной среды используется 3.10.2).
>>> print("hello)
File "<stdin>", line 1
print("hello)
^
SyntaxError: unterminated string literal (detected at line 1)
>>>
Сообщение об ошибке содержит две части: местоположение ошибки, а также тип и описание ошибки. Начнем с первой части, которая проиллюстрирована в только что приведенном примере.
File "<stdin>", line 1
print("hello)
^
В первом столбце будет указано, в какой программе, в каком файле произошла ошибка.
File "<stdin>", line 1
--------- ------
^ ^
| |
發生錯誤的檔案 -- 檔案裡的哪一列發生錯誤
Когда мы тестируем программу в интерактивной среде Python, имя файла будет <stdin>, stdin означает стандартное устройство ввода, которым является ваша клавиатура, указывая на то, что программа была введена непосредственно в интерактивную среду Python через клавиатуру.
Во втором столбце будет показан столбец, в котором произошла ошибка, и место в этом столбце, где произошла ошибка.
print("hello)
^
Вы увидите содержимое программы, и она укажет место ошибки знаком ‘^’, как в данном случае в начале строки. Если это простая ошибка, вы, вероятно, узнаете проблему, посмотрев сюда, но не имеет значения, если вы не можете ее увидеть, посмотрите на вторую часть сообщения об ошибке, и вы узнаете подробности ошибки.
Вторая часть сообщения об ошибке делится на тип ошибки и описание, как это поясняется в только что приведенном примере.
SyntaxError: unterminated string literal (detected at line 1)
----------- ------------------------------------------------
^ ^
| |
錯誤類型 錯誤的詳細說明
В данном случае тип ошибки — SyntaxError, что переводится как «ошибка синтаксиса» и означает, что Python не написал программу в соответствии с правилами Python, поэтому Python не может выполнить программу после прочтения ее содержимого.
В описании ошибки говорится, что мы столкнулись с нетерминированным литералом, который является термином программирования для записи данных непосредственно в текст, таких как целое число 23, число с плавающей точкой 5.36, строка «hello» и т.д. Итак, все описание говорит нам следующее Поскольку Python требует, чтобы строка была заключена в пару кавычек, первая часть сообщения об ошибке указывает на отсутствие двойной кавычки после hello, поэтому вы можете просто заполнить ее. Кроме того, в конце описания вам любезно сообщают, что ошибка была обнаружена в первой колонке программы.
Важно отметить, что сообщение об ошибке не обязательно указывает на местоположение отсутствующего типа, но он должен находиться рядом.
Сообщения об ошибках синтаксиса при выполнении полного файла программы
Если вы запускаете файл программы, например, возьмем пример, который мы только что написали в файле test.py.
❯ type test.py
print("hello)
Затем из терминала выполните командную строку
❯ py test.py
File "D:codepythontest.py", line 1
print("hello)
^
SyntaxError: unterminated string literal (detected at line 1)
❯
Вы увидите точно такое же сообщение об ошибке, за исключением того, что место ошибки отмечено фактическим именем файла, а не «stdin», которое представляет собой ввод с клавиатуры.
Сообщения об ошибках синтаксиса в Visual Studio Code и других инструментах разработки
Многие люди используют инструменты разработки для написания программ. Вот пример из Visual Studio Code, где открытие файла test.py, который мы только что запустили, открывает панель терминала в нижней половине и запускает его из командной строки, поэтому мы видим то же сообщение об ошибке.
Модуль расширения Pylance, установленный в Visual Studio Code, например, показывает красную линию, где была обнаружена синтаксическая ошибка, и если вы наведете курсор на эту линию, вы увидите сообщение.
Например, изображение выше говорит о том, что написанная здесь строка не имеет окончания.
Кроме того, Pylance также отображает все обнаруженные синтаксические ошибки в панели вопросов ниже.
Например, на изображении выше показаны две синтаксические ошибки, поэтому просто нажмите на сообщение об ошибке, и ошибка будет отмечена в панели редактирования. В этом случае первой ошибкой является
"(" was not closed
Это означает, что «(» не закрывается, а значит, нет соответствующего «)».
Вторая ошибка говорит нам о том, что написанная строка не имеет окончания.
String literal is unterminated
Эта ошибка также вызывает первую ошибку, поскольку строка не имеет окончания, поэтому «)», который соответствует «(«, рассматривается как содержимое строки, а «(» не имеет соответствующего «)».
Сообщения об ошибках синтаксиса в Colab или Jupyter
Если вы запускаете формулу в Colab, вы увидите следующее сообщение об ошибке.
Вы можете видеть, что формат сообщения об ошибке похож на описанный выше, но с двумя отличиями.
-
В Colab сообщение об ошибке выдается по ячейкам, поэтому после ‘File’ указывается идентификатор ячейки в Colab, а указанный номер столбца также является номером столбца ячейки.
File "<ipython-input-1-2fadf01e7f7a>", line 1
Число после ‘ipython-input-‘ — это номер выполнения ячейки, как в примере выше, что означает, что ошибка была в выполнении ячейки номер 1.
-
Поскольку во время моего тестирования Colab использовал Python версии 3.7.12, сообщение об ошибке, отображаемое разными версиями Python, может отличаться, например, указанная здесь позиция ошибки находится после правой скобки.
print("hello) ^
-
Тип ошибки тот же, но сообщение об ошибке — ‘End Of Line (EOL) encountered while scanning the contents of a written string’, что означает, что колонка завершилась, не увидев перевернутой запятой в конце строки.
SyntaxError: EOL while scanning string literal
Поэтому ошибка отмечается в конце программы.
-
Colab также любезно предоставила кнопку ссылки на StackOverflow после сообщения об ошибке, чтобы вы могли перейти на сайт для получения ответов.
Синтаксические ошибки в Jupyter (IPython)
Если вы выполняете программу в Jupyter (IPython), вы увидите сообщения об ошибках в формате, аналогичном Colab.
Однако место ошибки обозначается номером выполнения ячейки памяти вместо более длинного и сложного идентификационного имени в Colab
Input In [1]
print("hello)
^
Однако в ячейке нет номера столбца, только номер столбца в конце сообщения об ошибке: Введите полноэкранный режим
SyntaxError: unterminated string literal (detected at line 1)
Поскольку эта среда Jupyter работает на Python 3.10.2, сообщения об ошибках такие же, как и в интерактивной среде.
Ошибка времени выполнения
Ошибка времени выполнения — это ошибка, которая возникает после выполнения программы, в отличие от синтаксической ошибки, которая возникает до выполнения программы.
Сообщения об ошибках выполнения в интерактивной среде
Давайте рассмотрим простой пример, иллюстрирующий ошибку времени выполнения.
>>> a = 20
>>> print(a[2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not subscriptable
>>>
В данном примере ошибка возникает потому, что мы используем целое число как объект, например, серию, и пытаемся получить элемент с индексом 2. Сообщение об ошибке, как и синтаксическая ошибка, делится на две части: место ошибки и тип и описание ошибки.
TypeError: 'int' object is not subscriptable
Он сообщает нам, что это TypeError, что означает, что этот тип данных не может быть использован здесь, а последующее описание прямо объясняет, что объекты int не могут быть индексированными (subscriptable), т.е. они не могут быть использованы с оператором []
. Поняв это, вы сможете найти столбец кода, в котором произошла ошибка, увидеть оператор []
, узнать, что оператор a
является целым числом и не может использоваться с оператором []
, и устранить проблему.
Помимо имени файла и номера колонки, в начале местоположения ошибки есть дополнительная колонка, начинающаяся с сообщения «Traceback», которое возвращает вас назад во времени к процессу выполнения, вызвавшему возникновение ошибки.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Однако этот пример содержит только одну строку кода, поэтому увидеть значение трассировки невозможно, поэтому вместо этого воспользуемся следующим примером.
>>> def f(a):
... return a[2]
...
>>> print(f(20))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
TypeError: 'int' object is not subscriptable
>>>
Вы увидите, что в истории отката есть два столбца, первый столбец выглядит следующим образом
File "<stdin>", line 1, in <module>
Это говорит нам о том, что в первом столбце программы есть ошибка, за которой следует «in <module>», что означает, что программа не находится в какой-либо категории или функции, а находится на самом внешнем уровне программного файла. Поскольку ошибка находится в функции f()
, ошибка находится в этой функции, поэтому вам нужно посмотреть на следующий столбец в истории отказов, чтобы увидеть, где находится ошибка.
File "<stdin>", line 2, in f
Это говорит нам о том, что во втором столбце функции f()
произошла ошибка типа, поэтому просто следуйте описанию ошибки, чтобы узнать, что пошло не так в этом столбце.
Важно отметить, что история обратного хода располагается в порядке последнего вызова последним, так как в только что показанном примере программа выполняется первой
>>> print(f(20))
перед переходом к столбцу 2 функции f()
.
>>> def f(a):
... return a[2]
...
Это порядок, в котором они перечислены в истории обратного пути.
Сообщения об ошибках во время выполнения полного файла программы
Если вы запускаете полный файл программы, напр.
❯ type test.py
def f(a):
return a[2]
print(f(20))
Сообщение об ошибке выглядит следующим образом.
❯ py test.py
Traceback (most recent call last):
File "D:codepythontest.py", line 4, in <module>
print(f(20))
File "D:codepythontest.py", line 2, in f
return a[2]
TypeError: 'int' object is not subscriptable
❯
Отличие от того, что наблюдается в интерактивной среде, заключается в том, что
- Как и в случае с синтаксической ошибкой, она помечается реальным именем файла.
- Номера столбцов программы располагаются в порядке возрастания общего номера в файле программы.
- Помимо имени файла и номера столбца, для удобства просмотра также указывается программа, в которой произошла ошибка.
Ошибки времени выполнения в Colab
Если вы запускаете ту же программу в Colab, вы увидите следующие сообщения об ошибках.
Сообщение аналогично, но в нем для справки перечисляется программа, находящаяся рядом с ошибкой, а также указывается, какая программа находится в колонке ошибок.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-516efd866f6a> in <module>()
2 return a[2]
3
----> 4 print(f(20))
<ipython-input-5-516efd866f6a> in f(a)
1 def f(a):
----> 2 return a[2]
3
4 print(f(20))
TypeError: 'int' object is not subscriptable
Если фактическая ошибка находится в другой ячейке, вы можете найти эту ячейку, используя номер выполнения в идентификационном имени, например, если новая ячейка называется f()
.
Хорошо видно, что ячейка с номером выполнения 6 вызвала f()
из ячейки с номером выполнения 5 и произошла ошибка: f()
.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-925a89c490fa> in <module>()
----> 1 print(f(200))
<ipython-input-5-516efd866f6a> in f(a)
1 def f(a):
----> 2 return a[2]
3
4 print(f(20))
TypeError: 'int' object is not subscriptable
Ошибка периода выполнения в Jupyter
Jupyter помечается аналогично Colab, но в отличие от синтаксических ошибок, ошибки времени выполнения отображаются с номером столбца.
Также очень любезно дополнительно указать разными цветами, где находится ошибка в колонке программы, в которой она возникла.
Если ошибка находится в другой ячейке, она указывается таким же образом.
Видно, что ошибка вызвана тем, что выполнение ячейки 4 вызывает f()
из выполнения ячейки 2.
Ошибка возникает при использовании другого модуля
Имея эту основу, вы можете успокоиться, когда столкнетесь с ошибкой, например, при использовании модуля Python, который выдает ошибку
>>> import os.path
>>> os.path.getatime("xxx.txt")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:Program FilesPython310libgenericpath.py", line 60, in getatime
return os.stat(filename).st_atime
FileNotFoundError: [WinError 2] 系統找不到指定的檔案。: 'xxx.txt'
>>>
Здесь мы пытаемся получить время последнего доступа к определенному файлу, и, отступая назад, мы видим, что на самом деле это была ошибка при вызове os.stat()
, но в Windows сообщение об ошибке на китайском языке, поэтому его легко понять. Эта же программа на Linux — на английском языке.
>>> import os.path
>>> os.path.getatime("xxx.txt")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.9/genericpath.py", line 60, in getatime
return os.stat(filename).st_atime
FileNotFoundError: [Errno 2] No such file or directory: 'xxx.txt'
>>>
Но если вы внимательно прочитаете его, то увидите, что проблема заключается в том, что указанный файл не существует. Еще одним преимуществом чтения сообщений об ошибках является то, что вы можете увидеть детали реализации, например, в этом случае мы видим, что os.path.getatime()
достигается os.stat()
, а для дальнейших деталей мы знаем, где находится исходный файл, по адресу Найдите столбец 60 в genericpath.py, и вы увидите фактическое содержание
57
58 def getatime(filename):
59 """Return the last access time of a file,reported by os.stat()."""
60 return os.stat(filename).st_atime
61
Разве не выгодно совершить ошибку и при этом чему-то научиться?
Резюме
На данный момент у нас есть базовые навыки, осталось только понять ключевые слова, когда мы видим сообщения об ошибках. Например, следующая ошибка.
>>> for i in 20:
... print(i)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>>
В сообщении об ошибке говорится, что объект int
не является iterable
, так что же такое iterable
? Мы не можем объяснить все сообщения об ошибках в этой статье, нам придется самим искать документацию, поэтому базовые навыки все равно неизбежны.