Monty Shokeen Last updated Jun 16, 2017
Read Time: 6 min
При выполнении программ очень часто встречаются ошибки. Два распространенных типа ошибок, с которыми вам приходится иметь дело — ошибки синтаксиса и исключения. Синтаксические ошибки возникают при неправильном наборе кода. В таких случаях строка с ошибкой повторяется парсером со стрелкой, указывающей на самое раннее место, где была обнаружена ошибка.
Исключения отличаются от синтаксических ошибок. Они возникают во время выполнения программы, когда происходит что-то неожиданное. Например, допустим, вы просите пользователя ввести число для выполнения деления. Теперь, если пользователь вводит строку вместо числа, а вы пытаетесь разделить число на указанные данные, программа выведет TypeError .
При неправильной обработке исключения, программа прекратит работу, так как не знает, что делать в таких случаях. Следующий код, показывает такой случай:
Курс Python: Урок #5. Комментирование кода
keep_asking = True
while keep_asking:
x = int(input(«Enter a number: «))
print(«Dividing 50 by», x,»will give you :», 50/x)
Пока вы вводите значение в виде целого числа, программа будет работать правильно. Однако, как только вы введёте строку или даже десятичное число, вы получите исключение ValueError .
Из этого урока вы узнаете, как правильно обрабатывать и создавать исключения в Python.
Некоторые общие исключения
Вот некоторые основные исключения, которые могут возникнуть при написании программ. Вы можете прочитать о многих других встроенных исключениях на официальном сайте.
- NameError: это исключение возникает, когда программа не может найти локальное или глобальное имя. Имя, которое не удалось найти, включено в сообщение об ошибке.
- TypeError: это исключение возникает, когда функция передается объекту несоответствующего типа в качестве аргумента. Более подробная информация о неправильном типе содержится в сообщении об ошибке.
- ValueError: это исключение возникает, когда аргумент функции имеет правильный тип, но недопустимое значение.
- NotImplementedError: это исключение возникает, когда объект должен поддерживать операцию, но он ещё не реализован. Вы не должны использовать эту ошибку, если данная функция не предназначена для поддержки типа входящего аргумента. В таких ситуациях более целесообразно подбрасывать исключение TypeError .
- ZeroDivisionError: это исключение возникает, когда вы предоставляете второй аргумент для операции деления по модулю равный ноль.
- FileNotFoundError: это исключение возникает, когда файл или каталог, запрошенные программой, не существуют.
Так же, как и названия перечисленные выше, у большинства исключений понятные имена.
Обработка исключения
Код в начале статьи просил пользователей ввести целое число. Если пользователь не предоставлял целое число, программа прекращала работу и вызвала исключение по ошибке значения. В этом разделе мы напишем некоторый код, чтобы сообщить пользователю, что то, что он ввёл не является допустимым целым значением.
Урок 10 Строки: индексы и срезы Python
Первым шагом процесса является включение кода, который, по вашему мнению, может вызвать исключение внутри блока try . Следующий шаг — использовать ключевое слово except для обработки исключения, которое произошло в приведенном выше коде. Изменённый код для пользовательского ввода будет выглядеть так:
keep_asking = True
while keep_asking:
x = int(input(«Please enter a number: «))
print(«Dividing 50 by», x,»will give you :», 50/x)
except ValueError:
print(«The input was not an integer. Please try again. «)
Здесь происходит так, что программа пытается выполнить код внутри блока try . Если исключение не возникло, программа пропускает предложение except и остальная часть кода выполняется нормально. Если возникает исключение, программа пропускает оставшийся код внутри блока try , а тип исключения сопоставляется с именем исключения после ключевого слова except . В случае совпадения, сначала выполняется код под except , а, затем, после try , остальная часть кода выполняется нормально.
Когда вы вводите целое число, программа дает окончательный результат деления. Когда предоставляется нецелое значение, программа печатает сообщение с просьбой снова ввести целое число. Обратите внимание, что на этот раз программа не прерывается, когда вы предоставляете какие-либо недопустимые данные.
У вас может быть несколько except , для обработки разных исключений. Имейте в виду, что эти обработчики будут иметь дело только с исключениями, которые произошли в соответствующем блоке try . Исключения, возникающие в других обработчиках исключений обрабатываться не будут.
Вы также можете обрабатывать несколько исключений с помощью отдельного блока except , передавая эти исключения как tuple .
except (ZeroDivisionError, ValueError, TypeError):
print(«Something has gone wrong..»)
# code to deal with the exception
Наконец, вы также можете оставить название исключения после ключевого слова except . Обычно это не рекомендуется, так как теперь код будет захватывать все исключения и обрабатывать их таким же образом. Это не оптимальный вариант, так как исключение TypeError будет обрабатываться так же, как если бы вы обработали исключение ZeroDivisionError . При обработке исключений лучше быть как можно более конкретным и отлавливать только то, что вы можете обработать.
Одно из возможных способов использования всех исключений — правильно распечатать ошибку с исключением на экране, например, вот так:
import math
import sys
Источник: code.tutsplus.com
Оператор Python break
Использование циклов в Python автоматизирует и эффективно повторяет задачи. Но иногда может возникнуть условие, при котором вы хотите полностью выйти из цикла, пропустить итерацию или игнорировать это условие. Это может быть сделано с помощью операторов контроля цикла . Операторы управления циклом изменяют выполнение от его нормальной последовательности. Когда выполнение покидает область действия, все автоматические объекты, созданные в этой области, уничтожаются. Python поддерживает следующие операторы управления.
- Продолжить заявление
- Перерыв заявление
- Пройти заявление
В этой статье основное внимание будет уделено выражению break .
Перерыв заявление
Оператор break в Python используется для вывода элемента управления из цикла при срабатывании какого-либо внешнего условия. Оператор break ставится внутри тела цикла (как правило, после условия if).
Синтаксис:
break
Пример:
# Python программа для
# продемонстрировать оператор прерывания
# Использование для цикла
for letter in s:
# разорвать цикл, как только он увидит «е»
if letter = = ‘e’ or letter = = ‘s’ :
print ( «Out of for loop» )
# Использование цикла while
# разорвать цикл, как только он увидит «е»
if s[i] = = ‘e’ or s[i] = = ‘s’ :
print ( «Out of while loop» )
Выход:
g e Out of for loop g e Out of while loop
В приведенном выше примере оба цикла перебирают строку «geeksforgeeks», и как только они встречают символ «e» или «s», условие if становится истинным, и поток выполнения выводится из цикла.
- разбить, продолжить и пройти в Python
- с заявлением в Python
- Разбить список на куски размера N в Python
- Оператор возврата Python
- Python Продолжить заявление
- Python | Группировать элементы по позициям останова в списке
- Заявление, отступ и комментарий в Python
- Использование условного оператора else с циклом for в python
- Циклы и операторы управления (продолжить, разбить и пройти) в Python
- Как написать пустую функцию в выражении Python — pass?
- Чтение файловоподобных объектов Python из C | питон
- Python | Объединить значения ключа Python в список
- Python | Индекс ненулевых элементов в списке Python
- Python | Конвертировать список в массив Python
- Важные различия между Python 2.x и Python 3.x с примерами
Источник: espressocode.top
Exceptions Python
Если в коде есть ошибка, которую видит интерпретатор поднимается исключение, создается так называемый Exception Object, выполнение останавливается, в терминале показывается Traceback.
В английском языке используется словосочетание Raise Exception
Исключение, которое не было предусмотрено разработчиком называется необработанным (Unhandled Exception)
Такое поведение не всегда является оптимальным. Не все ошибки дожны останавливать работу кода. Возможно, где-то разработчик ожидает появление ошибок и их можно обработать по-другому.
try и except нужны прежде всего для того, чтобы код правильно реагировал на возможные ошибки и продолжал выполняться там, где появление ошибки некритично.
Исключение, которое предусмотрено в коде называется обработанным (Handled)
Блок try except имеет следующий синтаксис
try : pass except Exception : pass else : pass finally : pass
В этой статье я создал файл try_except.py куда копирую код из примеров.
Пример
Попробуем открыть несуществующий файл и воспользоваться базовым Exception
try : f = open ( ‘missing.txt’ ) except Exception : print ( ‘ERR: File not found’ )
ERR: No missing.txt file found
Ошибка поймана, видно наше сообщение а не Traceback
Проверим, что когда файл существует всё хорошо
try : f = open ( ‘existing.txt’ ) except Exception : print ( ‘ERR: File not found’ )
Пустота означает успех
Два исключения
Если ошибок больше одной нужны дополнительные исключения. Попробуем открыть существующий файл, и после этого добавить ошибку.
try : f = open ( ‘existing.txt’ ) x = bad_value except Exception : print ( ‘ERR: File not found’ )
ERR: File not found
Файл открылся, но так как в следующей строке ошибка — в терминале появилось вводящее в заблуждение сообщение. Проблема не в том, что «File not found» а в том, что bad_value нигде не определёно.
Избежать сбивающих с толку сообщений можно указав тип ожидаемой ошибки. В данном примере это FileNotFoundError
try : # expected exception f = open ( ‘existing.txt’ ) # unexpected exception should result in Traceback x = bad_value except FileNotFoundError : print ( ‘ERR: File not found’ )
Traceback (most recent call last): File «/home/andrei/python/try_except2.py», line 5, in x = bad_value NameError: name ‘bad_value’ is not defined
Вторая ошибка не поймана поэтому показан Traceback
Поймать обе ошибки можно добавив второй Exception
try : # expected exception should be caught by FileNotFoundError f = open ( ‘missing.txt’ ) # unexpected exception should be caught by Exception x = bad_value except FileNotFoundError : print ( ‘ERR: File not found’ ) except Exception : print ( ‘ERR: Something unexpected went wrong’ )
ERR: File not found
ERR: Something unexpected went wrong
Печать текста ошибки
Вместо своего текста можно выводить текст ошибки. Попробуем с существующим файлом — должна быть одна пойманная ошибка.
try : # expected exception should be caught by FileNotFoundError f = open ( ‘existing.txt’ ) # unexpected exception should be caught by Exception x = bad_value except FileNotFoundError as e: print (e) except Exception as e: print (e)
name ‘bad_value’ is not defined
Теперь попытаемся открыть несуществующий файл — должно быть две пойманные ошибки.
try : # expected exception should be caught by FileNotFoundError f = open ( ‘missing.txt’ ) # unexpected exception should be caught by Exception x = bad_value except FileNotFoundError as e: print (e) except Exception as e: print (e)
name ‘bad_value’ is not defined
[Errno 2] No such file or directory: ‘missing.txt’
else
Блок else будет выполнен если исключений не будет поймано.
Попробуем открыть существующий файл existing.txt в котором есть строка www.heihei.ru
try : f = open ( ‘existing.txt’ ) except FileNotFoundError as e: print (e) except Exception as e: print (e) else : print (f.read()) f.close()
Если попробовать открыть несуществующий файл missing.txt то исключение обрабатывается, а код из блока else не выполняется.
[Errno 2] No such file or directory: ‘missing.txt’
finally
Блок finally будет выполнен независимо от того, поймано исключение или нет
try : f = open ( ‘existing.txt’ ) except FileNotFoundError as e: print (e) except Exception as e: print (e) else : print (f.read()) f.close() finally : print ( «Finally!» )
А если попытаться открыть несуществующий missing.txt
[Errno 2] No such file or directory: ‘missing.txt’ Finally!
Когда нужно применять finally:
Рассмотрим скрипт, который вносит какие-то изменения в систему. Затем он пытается что-то сделать. В конце возвращает систему в исходное состояние.
Если ошибка случится в середине скрипта — он уже не сможет вернуть систему в исходное состояние.
Но если вынести возврат к исходному состоянию в блок finally он сработает даже при ошибке в предыдущем блоке.
import os def make_at (path, dir_name): original_path = os.getcwd() os.chdir(path) os.mkdir(dir_name) os.chdir(original_path)
Этот скрипт не вернётся в исходную директорию при ошибке в os.mkdir(dir_name)
А у скрипта ниже такой проблемы нет
def make_at (path, dir_name): original_path = os.getcwd() os.chdir(path) try : os.mkdir(dir_name) finally : os.chdir(original_path)
Не лишнима будет добавить обработку и вывод исключения
import os import sys def make_at (path, dir_name): original_path = os.getcwd() os.chdir(path) try : os.mkdir(dir_name) except OSError as e: print (e, file =sys.stderr) raise finally : os.chdir(original_path)
По умолчанию print() выводит в sys.stdout, но в случае ислючений логичнее выводить в sys.stderr
raise
Можно вызывать исключения вручную в любом месте кода с помощью raise.
try : f = open ( ‘outdated.txt’ ) if f.name == ‘outdated.txt’ : raise Exception except FileNotFoundError as e: print (e) except Exception as e: print ( ‘File is outdated!’ ) else : print (f.read()) f.close() finally : print ( «Finally!» )
File is outdated! Finally!
raise можно использовать для перевызова исключения, например, чтобы уйти от использования кодов ошибок.
Для этого достаточно вызвать raise без аргументов — поднимется текущее исключение.
Пример 2
Рассмотрим функцию, которая принимает числа прописью и возвращает цифрами
>>> from exc1 import convert >>> convert(«one three three seven».split()) 1337
Теперь передадим аргумент, который не предусмотрен в словаре
>>> convert(» something unseen «.split()) Traceback (most recent call last): File «», line 1, in File «/home/andrei/python/exc1.py», line 17, in convert number something») → KeyError
Обработать это исключение можно внеся изменения в функцию convert
convert (s): try : number = » for token in s: number += DIGIT_MAP[token] x = int (number) print ( «Conversion succeeded! x = » , x) except KeyError : print ( «Conversion failed!» ) x = — 1 return x
>>> from exc1 import convert >>> convert(«one nine six one».split()) Conversion succeeded! x = 1961 1961 >>> convert(«something unseen».split()) Conversion failed! -1
Эта обработка не спасает если передать int вместо итерируемого объекта
>>> convert(2022) Traceback (most recent call last): File «», line 1, in File «/home/andrei/python/exc1.py», line 17, in convert for token in s: TypeError: ‘int’ object is not iterable
Нужно добавить обработку TypeError
… except KeyError : print ( «Conversion failed!» ) x = — 1 except TypeError : print ( «Conversion failed!» ) x = — 1 return x
>>> from exc1 import convert >>> convert(«2022».split()) Conversion failed! -1
Избавимся от повторов, удалив принты, объединив два исключения в кортеж и вынесем присваивание значения x из try блока.
Также добавим докстринг с описанием функции.
def convert (s): «»»Convert a string to an integer.»»» x = — 1 try : number = » for token in s: number += DIGIT_MAP[token] x = int (number) except ( KeyError , TypeError ): pass return x
>>> from exc4 import convert >>> convert(«one nine six one».split()) 1961 >>> convert(«bad nine six one».split()) -1 >>> convert(2022) -1
Ошибки обрабатываются, но без принтов, процесс не очень информативен.
Грамотно показать текст сообщений об ошибках можно импортировав sys и изменив функцию
import sys DIGIT_MAP = < ‘zero’ : ‘0’ , ‘one’ : ‘1’ , ‘two’ : ‘2’ , ‘three’ : ‘3’ , ‘four’ : ‘4’ , ‘five’ : ‘5’ , ‘six’ : ‘6’ , ‘seven’ : ‘7’ , ‘eight’ : ‘8’ , ‘nine’ : ‘9’ , >def convert (s): «»»Convert a string to an integer.»»» try : number = » for token in s: number += DIGIT_MAP[token] return ( int (number)) except ( KeyError , TypeError ) as e: print (f «Conversion error: » , file =sys.stderr) return — 1
>>> from exc1 import convert >>> convert(2022) Conversion error: TypeError(«‘int’ object is not iterable») -1 >>> convert(«one nine six one».split()) 1961 >>> convert(«bad nine six one».split()) Conversion error: KeyError(‘bad’)
Ошибки обрабатываются и их текст виден в терминале.
С помощью !r выводится repr() ошибки
raise вместо кода ошибки
В предыдущем примере мы полагались на возвращение числа -1 в качестве кода ошибки.
Добавим к коду примера функцию string_log() и поработаем с ней
def string_log (s): v = convert(s) return log(v)
>>> from exc1 import string_log >>> string_log(«one two eight».split()) 4.852030263919617 >>> string_log(«bad one two».split()) Conversion error: KeyError(‘bad’) Traceback (most recent call last): File «», line 1, in File «/home/andrei/exc1.py», line 32, in string_log return log(v) ValueError: math domain error
convert() вернул -1 а string_log попробовал его обработать и не смог.
Можно заменить return -1 на raise. Это считается более правильным подходом в Python
def convert (s): «»»Convert a string to an integer.»»» try : number = » for token in s: number += DIGIT_MAP[token] return ( int (number)) except ( KeyError , TypeError ) as e: print (f «Conversion error: » , file =sys.stderr) raise
>>> from exc7 import string_log >>> string_log(«one zero».split()) 2.302585092994046 >>> string_log(«bad one two».split()) Conversion error: KeyError(‘bad’) Traceback (most recent call last): File «», line 1, in File «/home/andrei/exc7.py», line 31, in string_log v = convert(s) File «/home/andrei/exc7.py», line 23, in convert number += DIGIT_MAP[token] KeyError: ‘bad’
Пример 3
Рассмотрим алгоритм по поиску квадратного корня
def sqrt (x): «»»Compute square roots using the method of Heron of Alexandria. Args: x: The number for which the square root is to be computed. Returns: The square root of x. «»» guess = x i = 0 while guess * guess != x and i < 20 : guess = (guess + x / guess) / 2.0 i += 1 return guess def main (): print (sqrt( 9 )) print (sqrt( 2 )) if __name__ == ‘__main__’ : main()
При попытке вычислить корень от -1 получим ошибку
def main (): print (sqrt( 9 )) print (sqrt( 2 )) print (sqrt(- 1 ))
3.0 1.414213562373095 Traceback (most recent call last): File «/home/andrei/sqrt_ex.py», line 26, in main() File «/home/andrei/sqrt_ex.py», line 23, in main print(sqrt(-1)) File «/home/andrei/sqrt_ex.py», line 16, in sqrt guess = (guess + x / guess) / 2.0 ZeroDivisionError: float division by zero
guess = (guess + x / guess) / 2.0
Происходит деление на ноль
Обработать можно следующим образом:
def main (): try : print (sqrt( 9 )) print (sqrt( 2 )) print (sqrt(- 1 )) except ZeroDivisionError : print ( «Cannot compute square root » «of a negative number.» ) print ( «Program execution continues » «normally here.» )
Обратите внимание на то, что в try помещены все вызовы функции
3.0 1.414213562373095 Cannot compute square root of a negative number. Program execution continues normally here.
Если пытаться делить на ноль несколько раз — поднимется одно исключение и всё что находится в блоке try после выполняться не будет
def main (): try : print (sqrt( 9 )) print (sqrt(- 1 )) print (sqrt( 2 )) print (sqrt(- 1 ))
3.0 Cannot compute square root of a negative number. Program execution continues normally here.
Каждую попытку вычислить корень из -1 придётся обрабатывать отдельно. Это кажется неудобным, но в этом и заключается смысл — каждое место где вы ждёте ислючение нужно помещать в свой try except блок.
Можно обработать исключение так:
3.0 Traceback (most recent call last): File «/home/andrei/sqrt_ex3.py», line 17, in sqrt guess = (guess + x / guess) / 2.0 ZeroDivisionError: float division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File «/home/andrei/sqrt_ex3.py», line 30, in main() File «/home/andrei/sqrt_ex3.py», line 25, in main print(sqrt(-1)) File «/home/andrei/sqrt_ex3.py», line 20, in sqrt raise ValueError() ValueError
Гораздо логичнее поднимать исключение сразу при получении аргумента
def sqrt (x): «»»Compute square roots using the method of Heron of Alexandria. Args: x: The number for which the square root is to be computed. Returns: The square root of x. Raises: ValueError: If x is negative «»» if x < 0 : raise ValueError ( «Cannot compute square root of » f «negative number » ) guess = x i = 0 while guess * guess != x and i < 20 : guess = (guess + x / guess) / 2.0 i += 1 return guess def main (): print (sqrt( 9 )) print (sqrt(- 1 )) print (sqrt( 2 )) print (sqrt(- 1 )) if __name__ == ‘__main__’ : main()
3.0 Traceback (most recent call last): File «/home/avorotyn/python/lessons/pluralsight/core_python_getting_started/chapter8/sqrt_ex4.py», line 35, in main() File «/home/avorotyn/python/lessons/pluralsight/core_python_getting_started/chapter8/sqrt_ex4.py», line 30, in main print(sqrt(-1)) File «/home/avorotyn/python/lessons/pluralsight/core_python_getting_started/chapter8/sqrt_ex4.py», line 17, in sqrt raise ValueError( ValueError: Cannot compute square root of negative number -1
Пока получилось не очень — виден Traceback
Убрать Traceback можно добавив обработку ValueError в вызов функций
3.0 1.414213562373095 Cannot compute square root of negative number -1 Program execution continues normally here.
Исключения, которые не нужно обрабатывать
IndentationError, SyntaxError, NameError нужно исправлять в коде а не пытаться обработать.
Важно помнить, что использовать обработку исключений для замалчивания ошибок программиста недопустимо.
Список исключений
Список встроенных в Python исключений
Существуют следующие типы объектов Exception
BaseException +— SystemExit +— KeyboardInterrupt +— GeneratorExit +— Exception +— StopIteration +— StopAsyncIteration +— ArithmeticError | +— FloatingPointError | +— OverflowError | +— ZeroDivisionError +— AssertionError +— AttributeError +— BufferError +— EOFError +— ImportError | +— ModuleNotFoundError +— LookupError | +— IndexError | +— KeyError +— MemoryError +— NameError | +— UnboundLocalError +— OSError | +— BlockingIOError | +— ChildProcessError | +— ConnectionError | | +— BrokenPipeError | | +— ConnectionAbortedError | | +— ConnectionRefusedError | | +— ConnectionResetError | +— FileExistsError | +— FileNotFoundError | +— InterruptedError | +— IsADirectoryError | +— NotADirectoryError | +— PermissionError | +— ProcessLookupError | +— TimeoutError +— ReferenceError +— RuntimeError | +— NotImplementedError | +— RecursionError +— SyntaxError | +— IndentationError | +— TabError +— SystemError +— TypeError +— ValueError | +— UnicodeError | +— UnicodeDecodeError | +— UnicodeEncodeError | +— UnicodeTranslateError +— Warning +— DeprecationWarning +— PendingDeprecationWarning +— RuntimeWarning +— SyntaxWarning +— UserWarning +— FutureWarning +— ImportWarning +— UnicodeWarning +— BytesWarning +— EncodingWarning +— ResourceWarning
IndexError
Объекты, которые поддерживают протокол Sequence должны поднимать исключение IndexError при использовании несуществующего индекса.
IndexError как и KeyError относится к ошибкам поиска LookupError
Traceback (most recent call last): File «», line 1, in IndexError: list index out of range
ValueError
ValueError поднимается когда объект правильного типа, но содержит неправильное значение
Traceback (most recent call last): File «», line 1, in ValueError: invalid literal for int() with base 10: ‘text’
KeyError
KeyError поднимается когда поиск по ключам не даёт результата
>>> sites = dict(urn=1, heihei=2, eth1=3) >>> sites[«topbicycle»]
Traceback (most recent call last): File «», line 1, in KeyError: ‘topbicycle’
TypeError
TypeError поднимается когда для успешного выполнения операции нужен объект определённого типа, а предоставлен другой тип.
pi = 3.1415 text = «Pi is approximately » + pi
Traceback (most recent call last): File «str_ex.py», line 3, in text = «Pi is approximately » + pi TypeError: can only concatenate str (not «float») to str
Пример из статьи str()
SyntaxError
SyntaxError поднимается когда допущена ошибка в синтаксисе языка, например, использован несуществующий оператор.
Python 3.8.10 (default, Nov 14 2022, 12:59:47) [GCC 9.4.0] on linux Type «help», «copyright», «credits» or «license» for more information. >>> >>> >>> 0 <> 0 File «», line 1 0 <> 0 ^ SyntaxError: invalid syntax
Пример из статьи __future__
Источник: www.andreyolegovich.ru