Документация Python неофициальный перевод

errors.md

337 строк · 25.7 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.7/tutorial/errors.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 8. Ошибки и исключения89До сих пор мы лишь упоминали сообщения об ошибках, но если вы пробовали примеры, то, скорее всего, уже с ними сталкивались. Существует (как минимум) два различимых вида ошибок: *синтаксические ошибки* и *исключения*.1011## 8.1. Синтаксические ошибки1213Синтаксические ошибки, также известные как ошибки разбора, – пожалуй, самый распространённый вид неполадок, с которыми вы сталкиваетесь, пока учите Python:1415```python16>>> while True print('Hello world')17  File "<stdin>", line 118    while True print('Hello world')19                   ^20SyntaxError: invalid syntax21```2223Парсер повторяет проблемную строку и показывает маленькую «стрелку», указывающую на самую раннюю позицию в строке, где была обнаружена ошибка. Ошибка вызвана (или, по крайней мере, обнаружена) элементом *предшествующим* стрелке: в примере ошибка обнаружена у функции [`print()`](https://python-all.ru/3.7/library/functions.html#print), поскольку перед ней отсутствует двоеточие (`':'`). Имя файла и номер строки выводятся, чтобы было понятно, где искать, если входные данные поступили из сценария.2425## 8.2. Исключения2627Даже если оператор или выражение синтаксически верны, при попытке его выполнения может возникнуть ошибка. Ошибки, обнаруженные во время выполнения, называются *исключениями* и не являются безусловно фатальными: вы скоро научитесь обрабатывать их в программах на Python. Однако большинство исключений не обрабатываются программами и приводят к сообщениям об ошибках, как показано ниже:2829```python30>>> 10 * (1/0)31Traceback (most recent call last):32  File "<stdin>", line 1, in <module>33ZeroDivisionError: division by zero34>>> 4 + spam*335Traceback (most recent call last):36  File "<stdin>", line 1, in <module>37NameError: name 'spam' is not defined38>>> '2' + 239Traceback (most recent call last):40  File "<stdin>", line 1, in <module>41TypeError: Can't convert 'int' object to str implicitly42```4344Последняя строка сообщения об ошибке показывает, что произошло. Исключения бывают разных типов, и тип выводится как часть сообщения: в примере это [`ZeroDivisionError`](https://python-all.ru/3.7/library/exceptions.html#ZeroDivisionError), [`NameError`](https://python-all.ru/3.7/library/exceptions.html#NameError) и [`TypeError`](https://python-all.ru/3.7/library/exceptions.html#TypeError). Строка, выводимая как тип исключения, – это имя встроенного исключения, которое произошло. Это верно для всех встроенных исключений, но не обязательно для определяемых пользователем (хотя это полезное соглашение). Стандартные имена исключений – встроенные идентификаторы (не зарезервированные ключевые слова).4546Остальная часть строки содержит подробности в зависимости от типа исключения и того, что его вызвало.4748Предыдущая часть сообщения об ошибке показывает контекст, в котором произошло исключение, в виде трассировки стека. Обычно она содержит трассировку стека с перечислением строк исходного кода; однако строки, прочитанные из стандартного ввода, отображаться не будут.4950[Встроенные исключения](https://python-all.ru/3.7/library/exceptions.html#bltin-exceptions) содержит список встроенных исключений и их значение.5152## 8.3. Обработка исключений5354Можно писать программы, обрабатывающие выбранные исключения. В следующем примере показан запрос ввода у пользователя до тех пор, пока не будет введено целое число, но при этом пользователь может прервать программу (с помощью `Control-C` или того, что поддерживает операционная система); обратите внимание, что прерывание пользователем вызывает исключение [`KeyboardInterrupt`](https://python-all.ru/3.7/library/exceptions.html#KeyboardInterrupt).5556```python57>>> while True:58...     try:59...         x = int(input("Please enter a number: "))60...         break61...     except ValueError:62...         print("Oops!  That was no valid number.  Try again...")63...64```6566Инструкция [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try) работает следующим образом.6768- Сначала выполняется *try-блок* (инструкции между ключевыми словами [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try) и [`except`](https://python-all.ru/3.7/reference/compound_stmts.html#except)).69- Если исключение не произошло, *except-блок* пропускается, и выполнение инструкции [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try) завершается.70- Если при выполнении блока try возникает исключение, оставшаяся часть блока пропускается. Затем, если его тип совпадает с исключением, указанным после [`except`](https://python-all.ru/3.7/reference/compound_stmts.html#except) ключевого слова, выполняется блок except, и затем выполнение продолжается после оператора [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try).71- Если возникает исключение, которое не соответствует исключению, указанному в блоке except, оно передается внешним операторам [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try); если обработчик не найден, это *необработанное исключение* и выполнение останавливается с сообщением, как показано выше.7273Оператор [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try) может содержать более одного блока except для указания обработчиков разных исключений. Будет выполнен не более одного обработчика. Обработчики обрабатывают только исключения, возникшие в соответствующем блоке try, а не в других обработчиках того же оператора `try`. Блок except может указывать несколько исключений в виде кортежа в скобках, например:7475```python76... except (RuntimeError, TypeError, NameError):77...     pass78```7980Класс в блоке [`except`](https://python-all.ru/3.7/reference/compound_stmts.html#except) совместим с исключением, если это тот же класс или его базовый класс (но не наоборот – блок except, содержащий производный класс, несовместим с базовым классом). Например, следующий код выведет B, C, D в таком порядке:8182```python83class B(Exception):84    pass8586class C(B):87    pass8889class D(C):90    pass9192for cls in [B, C, D]:93    try:94        raise cls()95    except D:96        print("D")97    except C:98        print("C")99    except B:100        print("B")101```102103Обратите внимание, что если бы блоки except были переставлены (с `except B` первым), то вывелось бы B, B, B – срабатывает первый подходящий блок except.104105Последний блок except может опускать имена исключений, чтобы служить универсальным обработчиком. Используйте это с особой осторожностью, поскольку легко скрыть настоящую ошибку программирования таким образом! Его также можно использовать для вывода сообщения об ошибке и последующего повторного возбуждения исключения (позволяя вызывающему коду также обработать исключение):106107```python108import sys109110try:111    f = open('myfile.txt')112    s = f.readline()113    i = int(s.strip())114except OSError as err:115    print("OS error: {0}".format(err))116except ValueError:117    print("Could not convert data to an integer.")118except:119    print("Unexpected error:", sys.exc_info()[0])120    raise121```122123Оператор [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try) … [`except`](https://python-all.ru/3.7/reference/compound_stmts.html#except) имеет необязательную *часть else*, которая, если присутствует, должна следовать за всеми блоками except. Она полезна для кода, который должен быть выполнен, если блок try не вызвал исключение. Например:124125```python126for arg in sys.argv[1:]:127    try:128        f = open(arg, 'r')129    except OSError:130        print('cannot open', arg)131    else:132        print(arg, 'has', len(f.readlines()), 'lines')133        f.close()134```135136Использование блока `else` лучше, чем добавление дополнительного кода в блок [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try), поскольку это позволяет избежать случайного перехвата исключения, которое не было возбуждено кодом, защищённым инструкцией `try``except`.137138Когда возникает исключение, оно может иметь связанное значение, также известное как *аргумент* исключения. Наличие и тип аргумента зависят от типа исключения.139140Блок except может указывать переменную после имени исключения. Эта переменная связывается с экземпляром исключения, аргументы которого хранятся в `instance.args`. Для удобства экземпляр исключения определяет [`__str__()`](https://python-all.ru/3.7/reference/datamodel.html#object.__str__), так что аргументы можно вывести напрямую без обращения к `.args`. Можно также сначала создать экземпляр исключения, а затем возбудить его и добавить к нему любые атрибуты по желанию.141142```python143>>> try:144...     raise Exception('spam', 'eggs')145... except Exception as inst:146...     print(type(inst))    # экземпляр исключения147...     print(inst.args)     # аргументы, хранящиеся в .args148...     print(inst)          # __str__ позволяет выводить args напрямую, но может быть переопределён в подклассах исключений149...                          # но может быть переопределён в подклассах исключений150...     x, y = inst.args     # распаковать args151...     print('x =', x)152...     print('y =', y)153...154<class 'Exception'>155('spam', 'eggs')156('spam', 'eggs')157x = spam158y = eggs159```160161Если исключение имеет аргументы, они выводятся как последняя часть («подробности») сообщения для необработанных исключений.162163Обработчики исключений обрабатывают исключения не только при их непосредственном возникновении в блоке try, но и если они возникают внутри функций, вызываемых (даже косвенно) в блоке try. Например:164165```python166>>> def this_fails():167...     x = 1/0168...169>>> try:170...     this_fails()171... except ZeroDivisionError as err:172...     print('Handling run-time error:', err)173...174Handling run-time error: division by zero175```176177## 8.4. Возбуждение исключений178179Инструкция [`raise`](https://python-all.ru/3.7/reference/simple_stmts.html#raise) позволяет программисту принудительно вызвать указанное исключение. Например:180181```python182>>> raise NameError('HiThere')183Traceback (most recent call last):184  File "<stdin>", line 1, in <module>185NameError: HiThere186```187188Единственный аргумент [`raise`](https://python-all.ru/3.7/reference/simple_stmts.html#raise) указывает, какое исключение должно быть возбуждено. Это должен быть либо экземпляр исключения, либо класс исключения (класс, который наследуется от [`Exception`](https://python-all.ru/3.7/library/exceptions.html#Exception)). Если передается класс исключения, он будет неявно создан вызовом его конструктора без аргументов:189190```python191raise ValueError  # сокращение для 'raise ValueError()'192```193194Если нужно определить, было ли возбуждено исключение, но обрабатывать его не предполагается, более простая форма инструкции [`raise`](https://python-all.ru/3.7/reference/simple_stmts.html#raise) позволяет повторно возбудить исключение:195196```python197>>> try:198...     raise NameError('HiThere')199... except NameError:200...     print('An exception flew by!')201...     raise202...203An exception flew by!204Traceback (most recent call last):205  File "<stdin>", line 2, in <module>206NameError: HiThere207```208209## 8.5. Определяемые пользователем исключения210211Программы могут задавать собственные исключения, создавая новый класс исключения (см. [Классы](https://python-all.ru/3.7/tutorial/classes.html#tut-classes) для получения дополнительной информации о классах Python). Исключения обычно должны быть производными от класса [`Exception`](https://python-all.ru/3.7/library/exceptions.html#Exception), прямо или косвенно.212213Классы исключений можно определять так же, как любые другие классы, но обычно их делают простыми, часто предоставляя лишь несколько атрибутов, позволяющих обработчикам исключений извлекать информацию об ошибке. При создании модуля, который может вызывать несколько различных ошибок, распространённой практикой является создание базового класса для исключений, определённых в этом модуле, и наследование от него для создания конкретных классов исключений для разных условий ошибок:214215```python216class Error(Exception):217    """Базовый класс для исключений в этом модуле."""218    pass219220class InputError(Error):221    """Исключение, возникающее при ошибках ввода.222223    Атрибуты:224        expression -- входное выражение, в котором произошла ошибка225        message -- пояснение ошибки226    """227228    def __init__(self, expression, message):229        self.expression = expression230        self.message = message231232class TransitionError(Error):233    """Возникает, когда операция пытается выполнить переход состояния, который не234    разрешён.235236    Атрибуты:237        previous -- состояние в начале перехода238        next -- новое состояние, которое было запрошено239        message -- пояснение, почему конкретный переход не разрешён240    """241242    def __init__(self, previous, next, message):243        self.previous = previous244        self.next = next245        self.message = message246```247248Большинство исключений имеют имена, оканчивающиеся на «Error», подобно именованию стандартных исключений.249250Многие стандартные модули определяют собственные исключения для сообщения об ошибках, которые могут возникнуть в определяемых ими функциях. Дополнительная информация о классах представлена в главе [Классы](https://python-all.ru/3.7/tutorial/classes.html#tut-classes).251252## 8.6. Определение действий по очистке253254Инструкция [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try) имеет ещё один необязательный блок, предназначенный для определения действий по очистке, которые должны быть выполнены при любых обстоятельствах. Например:255256```python257>>> try:258...     raise KeyboardInterrupt259... finally:260...     print('Goodbye, world!')261...262Goodbye, world!263Traceback (most recent call last):264  File "<stdin>", line 2, in <module>265KeyboardInterrupt266```267268Если присутствует блок [`finally`](https://python-all.ru/3.7/reference/compound_stmts.html#finally), блок `finally` будет выполнен как последняя задача перед завершением инструкции [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try). Блок `finally` выполняется независимо от того, вызывает ли инструкция `try` исключение. В следующих пунктах рассматриваются более сложные случаи возникновения исключения:269270- Если исключение возникает во время выполнения блока `try`, оно может быть обработано блоком [`except`](https://python-all.ru/3.7/reference/compound_stmts.html#except). Если исключение не обработано блоком `except`, оно повторно возбуждается после выполнения блока `finally`.271- Исключение может возникнуть во время выполнения блока `except` или `else`. В этом случае исключение также повторно возбуждается после выполнения блока `finally`.272- Если инструкция `try` достигает инструкции [`break`](https://python-all.ru/3.7/reference/simple_stmts.html#break), [`continue`](https://python-all.ru/3.7/reference/simple_stmts.html#continue) или [`return`](https://python-all.ru/3.7/reference/simple_stmts.html#return), блок `finally` выполняется непосредственно перед выполнением инструкции `break`, `continue` или `return`.273- Если в `finally` блоке содержится оператор `return`, возвращаемое значение будет взято из оператора `return` блока `finally`, а не из оператора `return` блока `try`.274275Например:276277```python278>>> def bool_return():279...     try:280...         return True281...     finally:282...         return False283...284>>> bool_return()285False286```287288Более сложный пример:289290```python291>>> def divide(x, y):292...     try:293...         result = x / y294...     except ZeroDivisionError:295...         print("division by zero!")296...     else:297...         print("result is", result)298...     finally:299...         print("executing finally clause")300...301>>> divide(2, 1)302result is 2.0303executing finally clause304>>> divide(2, 0)305division by zero!306executing finally clause307>>> divide("2", "1")308executing finally clause309Traceback (most recent call last):310  File "<stdin>", line 1, in <module>311  File "<stdin>", line 3, in divide312TypeError: unsupported operand type(s) for /: 'str' and 'str'313```314315Как видите, блок [`finally`](https://python-all.ru/3.7/reference/compound_stmts.html#finally) выполняется в любом случае. Исключение [`TypeError`](https://python-all.ru/3.7/library/exceptions.html#TypeError), возбуждённое при делении двух строк, не обрабатывается блоком [`except`](https://python-all.ru/3.7/reference/compound_stmts.html#except) и поэтому повторно возбуждается после выполнения блока `finally`.316317В реальных приложениях блок [`finally`](https://python-all.ru/3.7/reference/compound_stmts.html#finally) полезен для освобождения внешних ресурсов (таких как файлы или сетевые соединения) независимо от того, было ли использование ресурса успешным.318319## 8.7. Предопределённые действия по очистке320321Некоторые объекты определяют стандартные действия по очистке, которые должны быть выполнены, когда объект больше не нужен, независимо от успеха или неудачи операции с этим объектом. Рассмотрим следующий пример, в котором предпринимается попытка открыть файл и вывести его содержимое на экран.322323```python324for line in open("myfile.txt"):325    print(line, end="")326```327328Проблема этого кода в том, что файл остаётся открытым в течение неопределённого времени после завершения выполнения этой части кода. В простых скриптах это не проблема, но может стать проблемой для более крупных приложений. Инструкция [`with`](https://python-all.ru/3.7/reference/compound_stmts.html#with) позволяет использовать такие объекты, как файлы, таким образом, чтобы гарантировать их своевременную и корректную очистку.329330```python331with open("myfile.txt") as f:332    for line in f:333        print(line, end="")334```335336После выполнения инструкции файл *f* всегда закрывается, даже если при обработке строк возникла проблема. Объекты, которые, подобно файлам, предоставляют предопределённые действия по очистке, сообщают об этом в своей документации.337