Я использую исключения в python как в исключительных, так и в неисключительных обстоятельствах.
Часто приятно иметь возможность использовать Исключение, чтобы указать «запрос не может быть выполнен», а не возвращать значение «Ошибка». Это означает, что вы / всегда / знаете, что возвращаемое значение - правильный тип, а не произвольно None или NotFoundSingleton или что-то еще. Вот хороший пример того, где я предпочитаю использовать обработчик исключений вместо условного для возвращаемого значения.
try:
dataobj = datastore.fetch(obj_id)
except LookupError:
# could not find object, create it.
dataobj = datastore.create(....)
Побочным эффектом является то, что при запуске datastore.fetch (obj_id) вам никогда не нужно проверять, имеет ли возвращаемое значение None, вы сразу же получаете эту ошибку бесплатно. Это противоречит аргументу: «Ваша программа должна иметь возможность выполнять все свои основные функции без каких-либо исключений».
Вот еще один пример, где исключения являются «исключительно» полезными для написания кода для работы с файловой системой, которая не подчиняется условиям гонки.
# wrong way:
if os.path.exists(directory_to_remove):
# race condition is here.
os.path.rmdir(directory_to_remove)
# right way:
try:
os.path.rmdir(directory_to_remove)
except OSError:
# directory didn't exist, good.
pass
Один системный вызов вместо двух, никаких условий гонки. Это плохой пример, потому что очевидно, что это приведет к ошибке OSError в большем количестве случаев, чем отсутствие каталога, но это «достаточно хорошее» решение для многих строго контролируемых ситуаций.