2012-02-17 4 views
1

Я обнаружил, что обрабатываю исключения, не указав тип исключения, когда я вызываю код, который взаимодействует с системными библиотеками, такими как shutil, http и т. Д., Все из которых могут выходить, если система находится в неожиданном состоянии (например, файл заблокирован, сеть недоступна, и т.д.)Только ошибки времени выполнения Python

try: 
    # call something 
except: 
    print("OK, so it went wrong.") 

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

Существует ли соглашение о том, что все ошибки времени выполнения происходят из некоторого общего базового класса исключений, который я могу использовать здесь? Или что-нибудь, что не связано с синтаксическими ошибками, ошибками импорта модулей и т. Д.? Даже KeyError Я бы рассмотрел ошибку, потому что я предпочитаю использовать dict.get(), если я не уверен на 100%, что ключ будет там.

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

UPDATE: OK, ответы заставили меня понять, я прошу неправильный вопрос - то, что я на самом деле интересно, если есть соглашение Python или явная рекомендация для библиотеки писателей использовать специальные базовые классы для их исключения , чтобы отделить их от более мирских SyntaxError & друзей.

Потому что, если есть соглашение для библиотек, я, как потребитель библиотеки, может делать общие предположения о том, что может быть выбрано, даже если конкретные случаи могут отличаться. Не уверен, что это имеет смысл?

UPDATE СНОВА: ответ Свен, наконец, привел меня, чтобы понять, что вместо того, чтобы сдаться и ловить все на высшем уровне, я могу справиться и уточнить исключения на более низких уровнях, поэтому верхний уровень нужно беспокоиться только о конкретный тип исключения с уровня ниже.

Спасибо!

+0

Спасибо, я обыскал, но не смог вырвать ясный ответ. Где различие между ошибками синтаксиса/программиста и ошибками времени выполнения? –

+0

Обратите внимание, что вы обычно не можете поймать 'SyntaxError' - он будет выброшен, если * компилирует * источник, задолго до его выполнения. Единственные случаи, когда 'SyntaxError' можно поймать, если ваш блок' try' содержит 'import',' exec', 'execfile()' или 'eval()'. –

+0

@SvenMarnach: Да, я был уверен, что видел, как эти обработчики типа не улавливают даже синтаксические ошибки, но это могло быть что-то еще, более тонкое. У меня нет чистого примера. Спасибо за исправление. –

ответ

6
  1. Всегда делайте блок try как можно меньшим.

  2. Только поймайте исключения, с которыми вы хотите обращаться. Посмотрите документацию о функциях, с которыми вы имеете дело.

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

Вы сказали, что «не хотите, чтобы список всех возможных типов исключений», но обычно это не так уж плохо. Открытие файла? Catch IOError. Работа с некоторым библиотечным кодом? У них часто есть свои собственные иерархии исключений с конкретным исключением верхнего уровня - просто поймите это, если вы хотите поймать какие-либо исключения из библиотеки. Будьте как можно более конкретными, иначе ошибки будут незамеченными раньше или позже.

Что касается соглашения об пользовательских исключениях в Python: они usually should be derived from Exception. Это также то, что большинство пользовательских исключений в стандартной библиотеке происходят из, так как минимум вы должны сделать, это использовать

except Exception: 

вместо голого except пункта, который также ловит KeyboardInterrupt и SystemExit. Как вы заметили, это все равно поймает множество исключений, которые вы не хотите ловить.

+0

Это очень хороший совет. – aculich

+0

Спасибо за совет мудреца! Я думаю, что «Исключение» может вызвать у меня проблемы с такими вещами, как «OverflowError», и я также считаю ошибку программиста. Но ваше замечание об исключениях, связанных с библиотекой, заставило меня задуматься - если я смогу подключить все наши внутренние модули к выбросам исключений, специфичных для конкретной библиотеки, это будет намного проще в обращении. Для модулей, где я уже это сделал, обработка ошибок намного проще. –

1

Как насчет RuntimeError: http://docs.python.org/library/exceptions.html#exceptions.RuntimeError

Если это не то, что вы хотите (и это вполне может не быть), посмотрите на список исключений на этой странице. Если вы смущены тем, как иерархия подходит друг к другу, я предлагаю вам потратить десять минут на изучение свойства __bases__ исключений, которые вас интересуют, чтобы посмотреть, какие базовые классы они разделяют. (Заметим, что __bases__ не закрыт по всей иерархии - вам также может понадобиться изучить базы суперкласса).

+1

«Это исключение в основном является реликвией предыдущей версии интерпретатора, оно больше не используется». – kindall

+0

@kindall: связанная страница имеет все встроенные исключения, поэтому OP может выбрать то, что ему нравится, как вы хорошо знаете. – Marcin

+0

Мне было известно о RuntimeError, но я не нашел четкой рекомендации для библиотек использовать его в качестве базы для всех ошибок времени выполнения ... Есть ли такая вещь? –

5

Ознакомьтесь с этим списком built-in exceptions в документах Python. Похоже, что вы в основном хотите поймать StandardError, хотя это также включает KeyError. Существуют также другие базовые классы, такие как ArithmeticError и EnvironmentError, которые иногда могут оказаться полезными.

Я нашел, что сторонние библиотеки получают свои пользовательские исключения от Exception, как описано здесь. Программисты также склонны повышать стандартные исключения Python, такие как TypeError, ValueError и т. Д. В соответствующих ситуациях. К сожалению, это затрудняет постоянную фиксацию ошибок библиотеки отдельно от других ошибок, полученных от Exception. Я хочу, чтобы Python определялся, например. a UserException базовый класс. Некоторые библиотеки объявляют базовый класс для своих исключений, но вам нужно знать, что это такое, импортировать модуль и явно их поймать.

Конечно, если вы хотите, чтобы поймать все кромеKeyError и, скажем, IndexError, наряду с исключениями сценария стопора, вы можете сделать это:

try: 
    doitnow() 
except (StopIteration, GeneratorExit, KeyboardInterrupt, SystemExit): 
    raise # these stop the script 
except (KeyError, IndexError): 
    raise # we don't want to handle these ones 
except Exception as e: 
    handleError(e) 

Правда, это становится хлопот пишите каждый раз.

+0

Приятно, мне не приходило в голову явно уловить и повторно поднять то, что я/не хочу/не хочу поймать. –

+0

«Я хочу, чтобы Python определялся, например, базовый класс UserException». - Это то, на что я тоже надеялся. Кажется нетипичным для Python, он обычно настолько силен с условностями. –