Я обычно предпочитаю обрабатывать исключения внутренне (например, try / except внутри вызываемой функции, возможно, возвращая None), потому что python динамически типизирован. В общем, я так или иначе считаю это суждением, но в динамически типизированном языке есть небольшие факторы, которые склоняют чашу весов в пользу отказа от передачи исключения вызывающей стороне:
- Любой, кто вызывает вашу функцию, не уведомляется об исключениях, которые могут возникнуть. Это становится своего рода искусством - знать, за какими исключениями вы охотитесь (а общих, за исключением блоков, следует избегать).
if val is None
немного проще, чем except ComplicatedCustomExceptionThatHadToBeImportedFromSomeNameSpace
. Серьезно, я ненавижу не забывать вводить from django.core.exceptions import ObjectDoesNotExist
текст в верхней части всех моих файлов django, чтобы справиться с действительно распространенным вариантом использования. В мире со статической типизацией позвольте редактору сделать это за вас.
Однако, честно говоря, это всегда суждение, и описываемая вами ситуация, когда вызываемая функция получает ошибку, которую она не может помочь, является отличной причиной для повторного создания значимого исключения. У вас есть точная правильная идея, но, если вы не исключение, предоставит более значимую информацию в трассировке стека, чем
AttributeError: 'NoneType' object has no attribute 'foo'
что в девяти случаях из десяти - это то, что абонент увидит, если вы вернете необработанное None, не беспокойтесь.
(Все это заставляет меня желать, чтобы исключения python имели cause
атрибуты по умолчанию, как в java, что позволяет передавать исключения в новые исключения, чтобы вы могли повторно выбросить все, что захотите, и никогда не терять исходный источник проблемы.)