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

errors.md

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

1> **Источник:** https://python-all.ru/3.0/tutorial/errors.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Ошибки и исключения89До сих пор мы лишь упоминали сообщения об ошибках, но если вы пробовали примеры, то, скорее всего, уже с ними сталкивались. Существует (как минимум) два различимых вида ошибок: *синтаксические ошибки* и *исключения*.1011## Синтаксические ошибки1213Синтаксические ошибки, также известные как ошибки разбора, – пожалуй, самый распространённый вид неполадок, с которыми вы сталкиваетесь, пока учите Python:1415```python16>>> while True print('Hello world')17  File "<stdin>", line 1, in ?18    while True print('Hello world')19                   ^20SyntaxError: invalid syntax21```2223Парсер повторяет строку с ошибкой и показывает маленькую «стрелку», указывающую на самое раннее место в строке, где была обнаружена ошибка. Ошибка вызвана (или по крайней мере обнаружена) токеном *перед* стрелкой: в примере ошибка обнаружена в функции [`print()`](https://python-all.ru/3.0/library/functions.html#print), поскольку перед ней отсутствует двоеточие (`':'`). Имя файла и номер строки выводятся, чтобы вы знали, где искать, если ввод поступил из скрипта.2425## Исключения2627Даже если оператор или выражение синтаксически верны, при попытке его выполнения может возникнуть ошибка. Ошибки, обнаруженные во время выполнения, называются *исключениями* и не являются безусловно фатальными: вы скоро научитесь обрабатывать их в программах на Python. Однако большинство исключений не обрабатываются программами и приводят к сообщениям об ошибках, как показано ниже:2829```python30>>> 10 * (1/0)31Traceback (most recent call last):32  File "<stdin>", line 1, in ?33ZeroDivisionError: int division or modulo by zero34>>> 4 + spam*335Traceback (most recent call last):36  File "<stdin>", line 1, in ?37NameError: name 'spam' is not defined38>>> '2' + 239Traceback (most recent call last):40  File "<stdin>", line 1, in ?41TypeError: coercing to Unicode: need string or buffer, int found42```4344Последняя строка сообщения об ошибке указывает, что произошло. Исключения бывают разных типов, и тип выводится как часть сообщения: типы в примере – [`ZeroDivisionError`](https://python-all.ru/3.0/library/exceptions.html#exceptions.ZeroDivisionError), [`NameError`](https://python-all.ru/3.0/library/exceptions.html#exceptions.NameError) и [`TypeError`](https://python-all.ru/3.0/library/exceptions.html#exceptions.TypeError). Строка, выводимая как тип исключения, – это имя встроенного исключения, которое произошло. Это верно для всех встроенных исключений, но не обязательно для пользовательских (хотя это полезное соглашение). Стандартные имена исключений – встроенные идентификаторы (не зарезервированные ключевые слова).4546Остальная часть строки содержит подробности в зависимости от типа исключения и того, что его вызвало.4748Предыдущая часть сообщения об ошибке показывает контекст, в котором произошло исключение, в виде трассировки стека. Обычно она содержит трассировку стека с перечислением строк исходного кода; однако строки, прочитанные из стандартного ввода, отображаться не будут.4950[*Встроенные исключения*](https://python-all.ru/3.0/library/exceptions.html#bltin-exceptions) содержит список встроенных исключений и их значение.5152## Обработка исключений5354Можно писать программы, обрабатывающие выбранные исключения. Посмотрите на следующий пример, который запрашивает у пользователя ввод до тех пор, пока не будет введено целое число, но позволяет прервать программу (с помощью `Control-C` или того, что поддерживает операционная система); обратите внимание, что прерывание, инициированное пользователем, сигнализируется возбуждением исключения [`KeyboardInterrupt`](https://python-all.ru/3.0/library/exceptions.html#exceptions.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.0/reference/compound_stmts.html#try) работает следующим образом.6768- Сначала выполняется *блок try* (инструкция(и) между ключевыми словами [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) и [`except`](https://python-all.ru/3.0/reference/compound_stmts.html#except)).69- Если исключение не возникло, *блок except* пропускается, и выполнение инструкции [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) завершается.70- Если во время выполнения блока try возникло исключение, оставшаяся часть блока пропускается. Затем, если его тип совпадает с исключением, указанным после ключевого слова [`except`](https://python-all.ru/3.0/reference/compound_stmts.html#except), выполняется блок except, и затем выполнение продолжается после инструкции [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try).71- Если возникает исключение, которое не соответствует исключению, указанному в блоке except, оно передается внешним инструкциям [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try); если обработчик не найден, это *необработанное исключение*, и выполнение останавливается с сообщением, как показано выше.7273Инструкция [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) может иметь более одного блока except для указания обработчиков разных исключений. Будет выполнен не более одного обработчика. Обработчики обрабатывают только исключения, возникшие в соответствующем блоке try, а не в других обработчиках той же инструкции [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try). Блок except может перечислять несколько исключений в виде кортежа в скобках, например:7475```python76... except (RuntimeError, TypeError, NameError):77...     pass78```7980Последний блок except может опускать имена исключений, чтобы служить универсальным обработчиком. Используйте это с особой осторожностью, поскольку легко скрыть настоящую ошибку программирования таким образом! Его также можно использовать для вывода сообщения об ошибке и последующего повторного возбуждения исключения (позволяя вызывающему коду также обработать исключение):8182```python83import sys8485try:86    f = open('myfile.txt')87    s = f.readline()88    i = int(s.strip())89except IOError as err:90    print("I/O error: {0}".format(err))91except ValueError:92    print("Could not convert data to an integer.")93except:94    print("Unexpected error:", sys.exc_info()[0])95    raise96```9798Инструкция [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) ... [`except`](https://python-all.ru/3.0/reference/compound_stmts.html#except) имеет необязательный *блок else*, который, если присутствует, должен следовать за всеми блоками except. Он полезен для кода, который должен быть выполнен, если блок try не возбудил исключение. Например:99100```python101for arg in sys.argv[1:]:102    try:103        f = open(arg, 'r')104    except IOError:105        print('cannot open', arg)106    else:107        print(arg, 'has', len(f.readlines()), 'lines')108        f.close()109```110111Использование блока [`else`](https://python-all.ru/3.0/reference/compound_stmts.html#else) лучше, чем добавление дополнительного кода в блок [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try), поскольку это позволяет избежать случайного перехвата исключения, которое не было возбуждено кодом, защищаемым инструкцией [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) ... [`except`](https://python-all.ru/3.0/reference/compound_stmts.html#except).112113Когда возникает исключение, оно может иметь связанное значение, также известное как *аргумент* исключения. Наличие и тип аргумента зависят от типа исключения.114115В блоке except можно указать переменную после имени исключения. Переменная связывается с экземпляром исключения, аргументы которого хранятся в `instance.args`. Для удобства экземпляр исключения определяет [`__str__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__str__), так что аргументы можно вывести напрямую, не обращаясь к `.args`. Также можно сначала создать экземпляр исключения, а затем возбудить его, добавив к нему любые атрибуты по желанию.116117```python118>>> try:119...    raise Exception('spam', 'eggs')120... except Exception as inst:121...    print(type(inst))    # экземпляр исключения122...    print(inst.args)     # аргументы, хранящиеся в .args123...    print(inst)          # __str__ позволяет выводить args напрямую, но может быть переопределён в подклассах исключений124...                         # но может быть переопределён в подклассах исключений125...    x, y = inst.args     # распаковать args126...    print('x =', x)127...    print('y =', y)128...129<class 'Exception'>130('spam', 'eggs')131('spam', 'eggs')132x = spam133y = eggs134```135136Если исключение имеет аргументы, они выводятся как последняя часть («подробности») сообщения для необработанных исключений.137138Обработчики исключений обрабатывают исключения не только при их непосредственном возникновении в блоке try, но и если они возникают внутри функций, вызываемых (даже косвенно) в блоке try. Например:139140```python141>>> def this_fails():142...     x = 1/0143...144>>> try:145...     this_fails()146... except ZeroDivisionError as err:147...     print('Handling run-time error:', err)148...149Handling run-time error: int division or modulo by zero150```151152## Возбуждение исключений153154Инструкция [`raise`](https://python-all.ru/3.0/reference/simple_stmts.html#raise) позволяет программисту принудительно вызвать указанное исключение. Например:155156```python157>>> raise NameError('HiThere')158Traceback (most recent call last):159  File "<stdin>", line 1, in ?160NameError: HiThere161```162163Единственный аргумент [`raise`](https://python-all.ru/3.0/reference/simple_stmts.html#raise) указывает исключение, которое нужно возбудить. Это должен быть либо экземпляр исключения, либо класс исключения (класс, производный от `Exception`).164165Если нужно определить, было ли возбуждено исключение, но вы не собираетесь его обрабатывать, более простая форма инструкции [`raise`](https://python-all.ru/3.0/reference/simple_stmts.html#raise) позволяет повторно возбудить исключение:166167```python168>>> try:169...     raise NameError('HiThere')170... except NameError:171...     print('An exception flew by!')172...     raise173...174An exception flew by!175Traceback (most recent call last):176  File "<stdin>", line 2, in ?177NameError: HiThere178```179180## Пользовательские исключения181182Программы могут определять собственные исключения, создавая новый класс исключения. Исключения, как правило, должны быть производными от класса [`Exception`](https://python-all.ru/3.0/library/exceptions.html#exceptions.Exception), прямо или косвенно. Например:183184```python185>>> class MyError(Exception):186...     def __init__(self, value):187...         self.value = value188...     def __str__(self):189...         return repr(self.value)190...191>>> try:192...     raise MyError(2*2)193... except MyError as e:194...     print('My exception occurred, value:', e.value)195...196My exception occurred, value: 4197>>> raise MyError('oops!')198Traceback (most recent call last):199  File "<stdin>", line 1, in ?200__main__.MyError: 'oops!'201```202203В этом примере стандартный метод [`__init__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__init__) класса `Exception` был переопределён. Новое поведение просто создаёт атрибут *value*. Это заменяет стандартное поведение, создающее атрибут *args*.204205Классы исключений можно определять так же, как любые другие классы, но обычно их делают простыми, часто предоставляя лишь несколько атрибутов, позволяющих обработчикам исключений извлекать информацию об ошибке. При создании модуля, который может вызывать несколько различных ошибок, распространённой практикой является создание базового класса для исключений, определённых в этом модуле, и наследование от него для создания конкретных классов исключений для разных условий ошибок:206207```python208class Error(Exception):209    """Base class for exceptions in this module."""210    pass211212class InputError(Error):213    """Exception raised for errors in the input.214215    Attributes:216        expression -- input expression in which the error occurred217        message -- explanation of the error218    """219220    def __init__(self, expression, message):221        self.expression = expression222        self.message = message223224class TransitionError(Error):225    """Raised when an operation attempts a state transition that's not226    allowed.227228    Attributes:229        previous -- state at beginning of transition230        next -- attempted new state231        message -- explanation of why the specific transition is not allowed232    """233234    def __init__(self, previous, next, message):235        self.previous = previous236        self.next = next237        self.message = message238```239240Большинство исключений определяются с именами, оканчивающимися на «Error», как и стандартные исключения.241242Многие стандартные модули определяют собственные исключения для сообщения об ошибках, которые могут возникнуть в определяемых ими функциях. Дополнительная информация о классах представлена в главе [*Классы*](https://python-all.ru/3.0/tutorial/classes.html#tut-classes).243244## Определение действий по очистке245246Инструкция [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) имеет еще один необязательный блок, предназначенный для определения действий по очистке, которые должны выполняться в любых обстоятельствах. Например:247248```python249>>> try:250...     raise KeyboardInterrupt251... finally:252...     print('Goodbye, world!')253...254Goodbye, world!255Traceback (most recent call last):256  File "<stdin>", line 2, in ?257KeyboardInterrupt258```259260Блок *finally* всегда выполняется перед выходом из инструкции [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try), независимо от того, произошло исключение или нет. Когда исключение произошло в блоке [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) и не было обработано блоком [`except`](https://python-all.ru/3.0/reference/compound_stmts.html#except) (или произошло в блоке [`except`](https://python-all.ru/3.0/reference/compound_stmts.html#except) или [`else`](https://python-all.ru/3.0/reference/compound_stmts.html#else)), оно возбуждается повторно после выполнения блока [`finally`](https://python-all.ru/3.0/reference/compound_stmts.html#finally). Блок [`finally`](https://python-all.ru/3.0/reference/compound_stmts.html#finally) также выполняется «на выходе», когда любой другой блок инструкции [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) покидается через инструкцию [`break`](https://python-all.ru/3.0/reference/simple_stmts.html#break), [`continue`](https://python-all.ru/3.0/reference/simple_stmts.html#continue) или [`return`](https://python-all.ru/3.0/reference/simple_stmts.html#return). Более сложный пример:261262```python263>>> def divide(x, y):264...     try:265...         result = x / y266...     except ZeroDivisionError:267...         print("division by zero!")268...     else:269...         print("result is", result)270...     finally:271...         print("executing finally clause")272...273>>> divide(2, 1)274result is 2275executing finally clause276>>> divide(2, 0)277division by zero!278executing finally clause279>>> divide("2", "1")280executing finally clause281Traceback (most recent call last):282  File "<stdin>", line 1, in ?283  File "<stdin>", line 3, in divide284TypeError: unsupported operand type(s) for /: 'str' and 'str'285```286287Как видите, блок [`finally`](https://python-all.ru/3.0/reference/compound_stmts.html#finally) выполняется в любом случае. [`TypeError`](https://python-all.ru/3.0/library/exceptions.html#exceptions.TypeError), возбужденное при делении двух строк, не обрабатывается блоком [`except`](https://python-all.ru/3.0/reference/compound_stmts.html#except) и поэтому возбуждается повторно после выполнения блока [`finally`](https://python-all.ru/3.0/reference/compound_stmts.html#finally).288289В реальных приложениях блок [`finally`](https://python-all.ru/3.0/reference/compound_stmts.html#finally) полезен для освобождения внешних ресурсов (таких как файлы или сетевые соединения), независимо от того, было ли использование ресурса успешным.290291## Предопределённые действия по очистке292293Некоторые объекты определяют стандартные действия по очистке, которые должны быть выполнены, когда объект больше не нужен, независимо от успеха или неудачи операции с этим объектом. Рассмотрим следующий пример, в котором предпринимается попытка открыть файл и вывести его содержимое на экран.294295```python296for line in open("myfile.txt"):297    print(line)298```299300Проблема этого кода в том, что он оставляет файл открытым на неопределенное время после завершения выполнения этой части кода. В простых скриптах это не проблема, но в больших приложениях может стать проблемой. Инструкция [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with) позволяет использовать такие объекты, как файлы, так, чтобы они всегда своевременно и корректно закрывались.301302```python303with open("myfile.txt") as f:304    for line in f:305        print(line)306```307308После выполнения инструкции файл *f* всегда закрывается, даже если при обработке строк возникла проблема. Объекты, которые, подобно файлам, предоставляют предопределённые действия по очистке, сообщают об этом в своей документации.309