Перевод «exception» на русский
Such practices are the exception, but migrant and refugee students may still trigger additional funding indirectly.
Такая практика представляет собой исключение, однако учащиеся из числа мигрантов и беженцев все же могут обусловливать выделение дополнительных финансовых средств косвенным образом.
This is a hard rule that has no exception.
Это должно быть жестким правилом, у которого нет никаких исключений.
They looked like humans with the exception that they were giants.
Они выглядели как люди, за исключением того, что они были гигантами.
And humans are no exception, including in the workplace.
И люди не являются исключением, в том числе и на рабочем месте.
But perhaps monopoly is not some strange exception.
Но, возможно, монополия не является каким-то странным исключением.
The only exception is the increased ground clearance for competitors.
Единственным исключением является увеличенный, по отношению к конкурентам, клиренс автомобиля.
The only exception is that public servants lease land where they work.
Единственное исключение — это то, что государственные служащие арендуют землю, на которой они работают.
Pre-trial detention thus becomes the rule, and release the exception.
Таким образом, предварительное заключение превращается в правило, а освобождение — в исключение.
Non-cooperation seems to be the rule and cooperation the exception in this regard.
В данной области «несотрудничество», по-видимому, является нормой, а сотрудничество — исключением.
There should be no exception even for so-called subcritical tests.
Не должно быть никакого исключения, даже для так называемых подкритических испытаний.
The ban should be truly comprehensive making inter alia no exception for so-called peaceful nuclear explosions.
Такой запрет должен быть поистине всеобъемлющим, не допуская, среди прочего, никаких исключений для так называемых мирных ядерных взрывов.
Serious natural disasters have become more the norm than the exception.
Серьезные стихийные бедствия все в большей степени становятся нормой, а не исключением.
That which had hitherto been the exception now became a necessity.
То, что до тех пор являлось исключением, стало теперь насущной потребностью.
Infants are no exception, even newborns.
Дети в этом вопросе не исключение, даже новорожденные.
Bees are an exception to these rules about gestures.
Это масло представляет собой исключение из правила, относящегося к жирам.
Naturally good overcomes evil and this film isn’t an exception.
Но, как обычно, добро побеждает зло, и этот фильм не исключение.
I say «probably» because there is an exception.
Я употребил слово «вероятно», поскольку здесь есть одно исключение.
Things like copyrights or trademarks fall under this exception.
Такие вещи, как авторские права или торговые марки подпадают под это исключение.
I’d say this was no exception.
Я бы сказал, что и этот раз не был исключением.
Возможно неприемлемое содержание
Примеры предназначены только для помощи в переводе искомых слов и выражений в различных контекстах. Мы не выбираем и не утверждаем примеры, и они могут содержать неприемлемые слова или идеи. Пожалуйста, сообщайте нам о примерах, которые, на Ваш взгляд, необходимо исправить или удалить. Грубые или разговорные переводы обычно отмечены красным или оранжевым цветом.
Исключение != ошибка
Многие программисты почему-то считают, что исключения и ошибки — это одно и то же. Кто-то постоянно кидает exception, кто-то через errorHandler превращает ошибки в исключения. Некоторые пытаются увеличить производительность, используя исключения. Но, на самом деле, exception и ошибки — это совершенно разные механизмы. Не надо одним механизмом заменять другой. Они созданы для разных целей.
Когда появился php5 с исключениями, а затем ZendFramework, который всегда кидает исключения — я не мог понять: чем же exception лучше моего любимого trigger_error()? Долго думал, обсуждал с коллегами и разобрался в этом вопросе. Теперь я чётко знаю, где использовать trigger_error(), а где throw new Exception().
В чём же принципиальная разница между ними?
Ошибки
Ошибки — это то, что нельзя исправить, об этом можно только сообщить: записать в лог, отправить email разработчику и извинится перед пользователем. Например, если мой движок не может подключиться к БД, то это ошибка. Всё. Точка. Без БД сайт не работает, и я не могу с этим ничего сделать. Поэтому я вызываю ales_kaput() и trigger_error(), а мой errorHandler отправит мне email и покажет посетителю сообщение «Извините, сайт не работает».
Exception
Исключения — это не ошибки, это всего лишь особые ситуации, которые нужно как-то обработать. Например, если в калькуляторе вы попробуете разделить на ноль, то калькулятор не зависнет, не будет отсылать сообщения разработчику и извинятся перед вами. Такие ситуации можно обрабатывать обычным if-ом. Строго говоря, исключения — это конструкция языка позволяющая управлять потоком выполнения. Это конструкция, стоящая в одном ряду с if, for и return. И всё. Этот механизм ничем более не является. Только управление потоком.
Их основное предназначение: пробрасывать по каскаду. Покажу это на примере: есть три функции, которые вызывают друг друга каскадом:
function b() < c(99); >function c($x) < if ($x === 0) < // Некоторая особенная ситуация, // которая должна остановить выполнение функций c() и b(), // а функция a() должна узнать об этом >return 100 / $x; >
Эту задачу можно было бы решить без механизма exception. Например, можно заставить все функции возвращать специальный тип (если ты матёрый пэхапэшник, то должен вспомнить PEAR_Error). Для простоты я обойдусь null-ом:
echo 'a-stop'; > function b() < echo 'b-begin'; $result = c(0); if ($result === null) < return null; >echo 'b-stop'; return true; > function c($x) < echo 'c-begin'; if ($x === 0) < return null; >echo 'c-stop'; return 100 / $x; >
a-begin
b-begin
c-begin
Делить на ноль нехорошо
Задача выполнена, но, обратите внимание, мне пришлось модифицировать промежуточную функцию b(), чтобы она пробрасывала результат работы нижестоящей функции выше по каскаду. А если у меня каскад из 5 или 10 функций? То мне пришлось бы модифицировать ВСЕ промежуточные функции. А если исключительная ситуация в конструкторе? То мне пришлось бы подставлять костыли.
А теперь решение с использованием Exception:
a(); function a() < echo 'a-begin'; try < b(); echo 'a-stop'; >catch (Exception $e) < echo $e->getMessage(); > > function b() < echo 'b-begin'; c(0); echo 'b-stop'; >function c($x) < echo 'c-begin'; if ($x === 0) < throw new Exception('Делить на ноль нехорошо'); >echo 'c-stop'; return 100 / $x; >
Результат выполнения будет идентичен. Функция b() осталась в первоначальном виде, не тронутая. Это особенно актуально, если у вас длинные каскады. И ещё объект $e может содержать дополнительную информацию о произошедшей ситуации.
Таким образом, получается, что ошибки и исключения — это совершенно разные инструменты для решения совершенно разных задач:
ошибка — не поправимая ситуация;
исключение – позволяет прервать выполнение каскада функций и пробросить некоторую информацию. Что-то вроде глобального оператора return. Если у Вас нет каскада, то вам достаточно использовать if или return.
Ошибки не всегда являются ошибками
Некоторые могут мне возразить: «Посмотри в Zend Framework — там всегда кидают исключения. Это best practics, и надо делать также. Даже если не удалось подключиться к БД, надо кидать исключение».
В этой статье я как раз хочу развеять это заблуждение. Zend действительно является best practics, но программисты Зенда находятся на другой лодке и делают другие вещи. Принципиальная разница между ними и мной в том, что они пишут универсальную библиотеку, которая будет использоваться во многих проектах. И они со своей колокольни не могут сказать, что является критической ошибкой, а что является поправимой.
Например, в вашем проекте может быть несколько MySQL серверов и вы можете переключаться между ними при падении одного из них. По этому, Zend_Db, как универсальная библиотека, кидает исключение, а что с ним делать — решайте сами. Exception это гибко — вы сами решаете на каком уровне и какой тип ситуаций ловить. Вы можете вывести сообщение об ошибке или попытаться исправить возникшую ситуацию, если знаете как. При написании универсальных библиотек необходимо всегда кидать исключения. Это делает библиотеку более гибкой.
В итоге, могу сказать, что у обоих механизмов есть свои особенности и, самое главное, что у них есть своё предназначение и эти предназначения нисколько не пересекаются. . Не надо использовать исключения для улучшения быстродействия или сообщения об ошибках. Не надо в классе My_Custom_Exception реализовывать какую-либо логику исправления ситуации. Этот класс должен быть пустым, он создаётся только что бы определить тип ситуации и поймать только то, что надо. Название класса ‘My_Custom_Exception’ это такой древовидный аналог линейному списку констант E_*** (E_NOTICE, E_WARNING, . ).
В php давно был разработан механизм обработки ошибок, и он отлично работает. Я им отлично пользуюсь там, где это надо.
Что такое исключения в программировании
Рассказ об ошибках, которые можно предусмотреть заранее.
Большинство наших проектов устроены так: когда во время работы программы возникает какая-то ошибка, то программа аварийно завершается. Иногда при этом она выдаёт сообщение об ошибке. Кажется, что это нормальная ситуация, но на самом деле большинство ошибок можно предусмотреть и научить программу правильно с ними работать. Для этого нам нужны обработчики ошибок.
Что такое обработчик ошибок
Чтобы программа знала, что делать, если возникла какая-то ошибка, используют обработчики исключительных ситуаций, или, проще говоря, обработчики исключений. Смысл такой:
- Мы заранее прикидываем, в каком месте и почему может возникнуть ошибка.
- Пишем в этом месте специальный код, который предупредит компьютер, что это плановая ошибка и что у нас уже есть решение, мол, всё под контролем.
- Компьютер применяет наше решение и переходит к следующей команде.
- Программа не падает, не завершается с ошибкой, а продолжает работать.
Такие обработчики есть не в каждом языке программирования, но большинство современных языков это умеют делать.
Пример программы без обработчика исключений
Допустим, у нас в программе на Python предусмотрено чтение данных из файла и есть такой код:
Но если на диске этого файла не будет, то компьютер, когда дойдёт до этой строчки, выдаст ошибку:
Давайте нарисуем это в виде простой схемы:
Получается, что наша задача — предусмотреть вариант, что на диске не будет нужного файла, и придумать поведение программы в этом случае. Используем для этого обработчик исключений.
Программа с обработчиком исключений
Если мы знаем, что в каком-то месте возможна ошибка, то можем тогда предусмотреть этот сценарий и подстраховаться. Для этого используют обработчик и делают так:
- В том месте, где можно предусмотреть ошибку, делают специальный блок.
- В этом блоке запускают команду и смотрят, будет ошибка или нет.
- Если ошибки нет — программа работает дальше.
- Если возникла ошибка — выполнятся то, что написано в обработчике ошибок, а потом программа работает дальше.
В этой ситуации программа не зависнет и не вывалится с ошибкой, а сама сможет её обработать и делать дальше то, что нужно:
try: file = open("myfile2.txt") except FileNotFoundError: print("Файл не найден, создаю новый") file = open("myfile2.txt","a")
Команда try — это начало нашего обработчика исключений. Она говорит компьютеру: «Попробуй выполнить вот эту команду, а мы посмотрим, что произойдёт».
Except — это какую ошибку мы ожидаем здесь увидеть. В нашем случае мы хотим предусмотреть случай, что такого файла нет, поэтому пишем стандартную ошибку для такой ситуации.
Сравните текст этой ошибки с тем, что нам выдал компьютер в предыдущем разделе.
В других языках конструкция обработчика исключений может выглядеть по-другому, но смысл тот же: говорим компьютеру, какую команду нужно выполнить и что делать, если появилась конкретная ошибка.
Когда что-то не предусмотрено — будет ошибка
Если программе в этом блоке встретится другая ошибка, не та, которую мы предусмотрели, то программа остановится и всё перестанет работать. Например, вот какие ошибки могут возникнуть с файлом:
- файл есть на диске, но к нему нет прав доступа;
- файл занят другой программой;
- сам диск повреждён и данные не читаются.
Во всех этих случаях программа сломается, потому что мы не предусмотрели эти ситуации:
Получается, всё нужно делать с обработкой исключений?
Нет, и вот почему:
- Обработка исключений занимает лишнее время, поэтому программа с ними работает медленнее, чем без них.
- Не всё можно предусмотреть. Если разработчик не знает, что здесь может быть ошибка, то и предусмотреть он это тоже не сможет.
- Конструкции с обработчиками делают код менее читаемым и понятным для человека. Ему нужно будет держать в голове точку начала обработки, понять, как обработка влияет на программу в целом, и выяснить, что будет с программой после работы обработчика ошибок.
Конечно, есть места в коде, которые лучше делать с обработкой ошибок: работа с файлами, сетевые запросы или получение внешних данных. Но запихивать исключения на каждую команду в программе точно не стоит.
Эксепшн что это
Базовым для всех типов исключений является тип Exception . Этот тип определяет ряд свойств, с помощью которых можно получить информацию об исключении.
- InnerException : хранит информацию об исключении, которое послужило причиной текущего исключения
- Message : хранит сообщение об исключении, текст ошибки
- Source : хранит имя объекта или сборки, которое вызвало исключение
- StackTrace : возвращает строковое представление стека вызывов, которые привели к возникновению исключения
- TargetSite : возвращает метод, в котором и было вызвано исключение
Например, обработаем исключения типа Exception:
try < int x = 5; int y = x / 0; Console.WriteLine($"Результат: "); > catch (Exception ex) < Console.WriteLine($"Исключение: "); Console.WriteLine($"Метод: "); Console.WriteLine($"Трассировка стека: "); >
Однако так как тип Exception является базовым типом для всех исключений, то выражение catch (Exception ex) будет обрабатывать все исключения, которые могут возникнуть.
Но также есть более специализированные типы исключений, которые предназначены для обработки каких-то определенных видов исключений. Их довольно много, я приведу лишь некоторые:
- DivideByZeroException : представляет исключение, которое генерируется при делении на ноль
- ArgumentOutOfRangeException : генерируется, если значение аргумента находится вне диапазона допустимых значений
- ArgumentException : генерируется, если в метод для параметра передается некорректное значение
- IndexOutOfRangeException : генерируется, если индекс элемента массива или коллекции находится вне диапазона допустимых значений
- InvalidCastException : генерируется при попытке произвести недопустимые преобразования типов
- NullReferenceException : генерируется при попытке обращения к объекту, который равен null (то есть по сути неопределен)
И при необходимости мы можем разграничить обработку различных типов исключений, включив дополнительные блоки catch:
static void Main(string[] args) < try < int[] numbers = new int[4]; numbers[7] = 9; // IndexOutOfRangeException int x = 5; int y = x / 0; // DivideByZeroException Console.WriteLine($"Результат: "); > catch (DivideByZeroException) < Console.WriteLine("Возникло исключение DivideByZeroException"); >catch (IndexOutOfRangeException ex) < Console.WriteLine(ex.Message); >Console.Read(); >
В данном случае блоки catch обрабатывают исключения типов IndexOutOfRangeException и DivideByZeroException. Когда в блоке try возникнет исключение, то CLR будет искать нужный блок catch для обработки исключения. Так, в данном случае на строке
numbers[7] = 9;
происходит обращение к 7-му элементу массива. Однако поскольку в массиве только 4 элемента, то мы получим исключение типа IndexOutOfRangeException. CLR найдет блок catch, который обрабатывает данное исключение, и передаст ему управление.
Следует отметить, что в данном случае в блоке try есть ситуация для генерации второго исключения — деление на ноль. Однако поскольку после генерации IndexOutOfRangeException управление переходит в соответствующий блок catch, то деление на ноль int y = x / 0 в принципе не будет выполняться, поэтому исключение типа DivideByZeroException никогда не будет сгенерировано.
Однако рассмотрим другую ситуацию:
try < object obj = "you"; int num = (int)obj; // System.InvalidCastException Console.WriteLine($"Результат: "); > catch (DivideByZeroException) < Console.WriteLine("Возникло исключение DivideByZeroException"); >catch (IndexOutOfRangeException)
В данном случае в блоке try генерируется исключение типа InvalidCastException, однако соответствующего блока catch для обработки данного исключения нет. Поэтому программа аварийно завершит свое выполнение.
Мы также можем определить для InvalidCastException свой блок catch, однако суть в том, что теоретически в коде могут быть сгенерированы самые разные типы исключений. А определять для всех типов исключений блоки catch, если обработка исключений однотипна, не имеет смысла. И в этом случае мы можем определить блок catch для базового типа Exception:
try < object obj = "you"; int num = (int)obj; // System.InvalidCastException Console.WriteLine($"Результат: "); > catch (DivideByZeroException) < Console.WriteLine("Возникло исключение DivideByZeroException"); >catch (IndexOutOfRangeException) < Console.WriteLine("Возникло исключение IndexOutOfRangeException"); >catch (Exception ex) < Console.WriteLine($"Исключение: "); >
И в данном случае блок catch (Exception ex)<> будет обрабатывать все исключения кроме DivideByZeroException и IndexOutOfRangeException. При этом блоки catch для более общих, более базовых исключений следует помещать в конце — после блоков catch для более конкретный, специализированных типов. Так как CLR выбирает для обработки исключения первый блок catch, который соответствует типу сгенерированного исключения. Поэтому в данном случае сначала обрабатывается исключение DivideByZeroException и IndexOutOfRangeException, и только потом Exception (так как DivideByZeroException и IndexOutOfRangeException наследуется от класса Exception).