Работа с ошибками. Как ловить исключения и что потом с...

Post on 14-Jan-2015

258 views 4 download

Tags:

description

Григорий Петров - Технический евангелист / NPTV / Россия, Москва В своем докладе Григорий расскажет о том, зачем в программах обрабатывать ошибки, какие они бывают и что нам предлагает python для работы с ними. http://www.it-sobytie.ru/events/2040

Transcript of Работа с ошибками. Как ловить исключения и что потом с...

Работа над ошибкамиКак поймать исключение и остаться в живых

Рассказывает и показывает

Петров Григорий

Технический евангелист Digital October

Что такое ошибка?

Что такое ошибка?

● Когда мы пишем код, у нас есть предположение о том, как он будет работать.

Что такое ошибка?

● Когда мы пишем код, у нас есть предположение о том, как он будет работать.

● Когда мы его запускаем, часть наших предположений оказываются ошибочными.

Что такое ошибка?

● Когда мы пишем код, у нас есть предположение о том, как он будет работать.

● Когда мы его запускаем, часть наших предположений оказываются ошибочными.

● Это — ошибки.

Что такое ошибка?

● Когда мы пишем код, у нас есть предположение о том, как он будет работать.

● Когда мы его запускаем, часть наших предположений оказываются ошибочными.

● Это — ошибки.● Просто ошибки. Не “ошибки в программе”.

Что такое ошибка?

Ошибка — это наши ошибочные предположения о том, как будет работать наш код.

Откуда берутся ошибки?

Разное окружение:“А на моем компьютере все работает!”… а у пользователей такого файла нету.

Откуда берутся ошибки?

Сложность -> Кошелек Миллера -> 7 ± 2“Рассмотрим эту простую функцию в 2000 строк кода…”

И что с ними делать?

И что с ними делать?

● Ничего не делать :)

И что с ними делать?

● Ничего не делать :)● Обрабатывать.

И что с ними делать?

● Ничего не делать :)● Обрабатывать.Ошибка — это несоответствие. Мы не можем “обработать несоответствие”.

И что с ними делать?

● Ничего не делать :)● Привести код в соответствие.

○ Реагировать на разное окружение.○ Исправить логику работы.

Исправление логики работы

Статические проверки:Компилятор/интерпретаторСтатический анализатор кода

Динамические проверки:Интерпретатор/runtimeASSERT / VERIFY / ENSURE

Реакция на разное окружение

Файл не найден?

Реакция на разное окружение

Файл не найден?Оборвалось сетевое подключение?

Реакция на разное окружение

Файл не найден?Оборвалось сетевое подключение?Неподдерживаемая ОС?

Реакция на разное окружение

Файл не найден?Оборвалось сетевое подключение?Неподдерживаемая ОС?Закончилась память?

Реакция на разное окружение

Файл не найден?Оборвалось сетевое подключение?Неподдерживаемая ОС?Закончилась память?WTF?!? И что в таком случае делать?

Где пролегает красная черта?

● Насколько разное окружение мы хотим поддерживать?

● Сколько времени мы готовы уделить борьбе со сложностью?

Где пролегает красная черта?

Идеальная программа:Работает везде, как мы задумали

Хак на коленке:Иногда работает на компьютере автора

Красная черта

Где пролегает красная черта?

Идеальная программа:Работает везде, как мы задумали

Хак на коленке:Иногда работает на компьютере автора

Наша черта. Где хотим, там и пролегает.

Первый промежуточный итог

В зависимости от наших целей мы адаптируем программу к разным окружениям.

Первый промежуточный итог

Ожидаемые ошибки

Разные окружения, которые мы хотим поддерживать.

Программа сама переживает несоответствие либо сообщает о нем пользователю.

Неожиданные ошибки

Разные окружения, которые мы не хотим поддерживать.

Программа завершается. Аварийно или красиво, на выбор разработчика.

Реализация в коде

Тривиальная — через if:

if os.path.exists(path):

cfg = json.load(open(path))

else:

cfg = {“ver”: VERSION}

Реализация в коде

Менее тривиальная — исключения:

try:

cfg = json.load(open(path))

except:

cfg = {“ver”: VERSION}

В чем разница?

В чем разница?

Чтобы ответить на этот вопрос, мне понадобится исторический экскурс.

В чем разница?

Чтобы ответить на этот вопрос, мне понадобится исторический экскурсв C.

За 10 000 лет до исключений

Нет никакой защиты: если не проверять все результаты, программа падает.

За 10 000 лет до исключений

Нету никакой защиты: если не проверять все результаты, программа падает. продолжает работать с испорченной памятью и может повредить данные пользователя. А потом падает.

Как это выглядело

Думаете, я вам покажу 1000 и 1 if? :)

Как это выглядело

Думаете, я вам покажу 1000 и 1 if? :)Исключений тогда не было, но ребята были не глупее, чем мы.

Как это выгляделоBOOL AddStrToFile(CHAR* str, CHAR* fname, OUT HANDLE* error)

{

PROLOGUE

ENSURE(IsValidStr(str));

HANDLE file = 0;

ENSURE(FileOpen(fname, OUT& file, OUT error));

REQUIRE(SUCCESS(error));

ENSURE(FileSeek(file, 0, SEEK_END));

ENSURE(FileWrite(file, fname));

REQUIRE(SUCCESS(error));

EPILOGUE

}

Как это выгляделоBOOL AddStrToFile(CHAR* str, CHAR* fname, OUT HANDLE* error)

{

PROLOGUE

ENSURE(IsValidStr(str));

HANDLE file = 0;

ENSURE(FileOpen(fname, OUT& file, OUT error));

REQUIRE(SUCCESS(error));

ENSURE(FileSeek(file, 0, SEEK_END));

ENSURE(FileWrite(file, fname));

REQUIRE(SUCCESS(error));

EPILOGUE

}

неожиданные ошибкиожидаемые ошибки

Как это выгляделоОжидаемая ошибка

...

if(!SUCCESS(error))

REQUIRE(error)

REQUIRE(error)

Неожиданная ошибка

if(!VERIFY(method1()))

ENSURE(method2())

ENSURE(method3())

ENSURE(method4())

Что дали исключения

Синтаксический сахар для цепочки if’ов.Меньше кода, смысл тот же.

Второй промежуточный итог

Исключения — это синтаксический сахар над двумя цепочками if’ов: для ожидаемых и неожиданных ошибок.

Второй промежуточный итог

Исключения — это синтаксический сахар над двумя цепочками if’ов: для ожидаемых и неожиданных ошибок.Мы адаптируемся под ожидаемые ошибки и аварийно завершаемся при неожиданных.

Как пользоваться?1. Пишем код без контроля ошибок2. Дописываем обработку ожидаемых ошибок3. Отлаживаем4. goto 25. profit

Как пользоваться?1. Пишем код без контроля ошибок2. Дописываем обработку ожидаемых ошибок3. Отлаживаем4. goto 25. profit

Здесь у нас две проблемы

Проблема иерархии исключений

Какие исключения бросает json.load?

Проблема иерархии исключений

Какие исключения бросает json.load?Какие-то.

Проблема неконсистентных API

Коды возврата ломают код обработки ошибок. Например:

mylib.create_connection()

Может вернуть None или исключение.

Что делать?

Что делать?

Что делать?

Терпеть и кушать кактус :)

1. Для кода стандартной библиотеки иметь под рукой справочник исключений.

2. Для своего кода выделить ожидаемые (Expected) и неожиданные (Unexpected) исключения.

3. Оборачивать внешние библиотеки.

Это все.

Можно задавать вопросы.

Петров ГригорийТехнический евангелист Digital Octobergrigory.v.p@gmail.comhttp://facebook.com/grigoryvp