Дешевая обработка исключений в Python?

Я прочитал в предыдущем ответе , что обработка исключений является дешевой на Python, поэтому мы не должны делать предварительную проверку.

Я не слышал об этом раньше, но я относительно новичок в Python. Обработка исключений означает динамический вызов и статический возврат, тогда как оператор if является статическим вызовом, статическим возвратом.

Как сделать проверку плохой, а try-except быть хорошим, похоже, наоборот. Может кто-нибудь объяснить это мне?

Ответ 1

Вы можете найти это сообщение полезным: Try/Except Performance in Python: простой тест, где Патрик Альтман сделал какое-то простое тестирование, чтобы увидеть, что производительность в предварительных условных проверках в различных сценариях (в данном случае это относится к словарным клавишам) и использует только исключения. Код также предоставляется, если вы хотите адаптировать его для проверки других условных обозначений.

Выводы, к которым он пришел:

Из этих результатов, я думаю, справедливо для быстрого определения ряда Выводы:

  • Если существует высокая вероятность того, что элемент не существует, то вам лучше проверить его с has_key.
  • Если вы не собираетесь делать что-либо с Исключением, если оно поднял, тогда вам лучше не если у вас есть кроме
  • Если, вероятно, элемент существует, то есть небольшое преимущество использования try/except блок вместо использования has_key, однако преимущество очень незначительное.

Ответ 2

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

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

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

Ответ 3

Отложив оценки производительности, которые другие говорили, руководящий принцип часто структурирован как "легче просить прощения, чем спрашивать разрешения" и "смотреть, прежде чем прыгать".

Рассмотрим эти два фрагмента:

# Look before you leap
if not os.path.exists(filename):
    raise SomeError("Cannot open configuration file")
f = open(filename)

против.

# Ask forgiveness ...
try:
  f = open(filename)
except IOError:
  raise SomeError("Cannot open configuration file")

Эквивалент? На самом деле, нет. ОС - многозадачные системы. Что произойдет, если файл был удален между тестом для вызова "существует" и "открытым"?

Что произойдет, если файл существует, но он не читается? Что, если это имя каталога вместо файла. Могут быть много возможных режимов отказа, и проверка их всех - это большая работа. Тем более, что "открытый" вызов уже проверяет и сообщает обо всех возможных ошибках.

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

Ответ 4

"Может кто-нибудь объяснить это мне?"

Зависит.

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

"Обработка исключений означает динамический вызов и статический возврат, тогда как оператор if является статическим вызовом, статическим возвратом."

Что означает "динамический вызов"? Поиск кадров стека для обработчика? Я предполагаю, что вы говорите. И "статический вызов" каким-то образом находит блок после оператора if.

Возможно, этот "динамический вызов" не является самой дорогостоящей частью операции. Возможно, оценка выражения if-выражения немного дороже, чем простое "try-it-and-fail".

Оказывается, что проверки внутренней целостности Python почти такие же, как и ваш if-statement, и их нужно делать в любом случае. Поскольку Python всегда проверяет, ваш if-statement (в основном) избыточен.

Вы можете прочитать о обработке исключений низкого уровня в http://docs.python.org/c-api/intro.html#exceptions.


Edit

Подробнее: Вопрос о том, есть ли исключение, не имеет значения.

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

Используйте то, что делает ваш код clear и значимым. Не тратьте время на такие микро-оптимизации.

Ответ 5

С Python легко проверить разные возможности для скорости - познакомиться с timeit module:

... пример сеанса (с использованием командной строки), который сравнивает стоимость использования hasattr() vs. try/, за исключением проверки отсутствующих и существующих атрибутов объекта.

% timeit.py 'try:' '  str.__nonzero__' 'except AttributeError:' '  pass'
100000 loops, best of 3: 15.7 usec per loop
% timeit.py 'if hasattr(str, "__nonzero__"): pass'
100000 loops, best of 3: 4.26 usec per loop
% timeit.py 'try:' '  int.__nonzero__' 'except AttributeError:' '  pass'
1000000 loops, best of 3: 1.43 usec per loop
% timeit.py 'if hasattr(int, "__nonzero__"): pass'
100000 loops, best of 3: 2.23 usec per loop

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

EDIT: параметр командной строки -n по умолчанию будет достаточно большим, чтобы время выполнения имело смысл. A цитата из руководства:

Если -n не задано, подходящее количество циклов вычисляется путем попытки последовательных степеней 10 до тех пор, пока общее время не достигнет как минимум 0,2 секунды.

Ответ 6

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

Обратите внимание, что проверка с помощью if-elif-else должна каждый раз оценивать условие. Обработка исключений, в том числе поиск обработчика исключений, происходит только в исключительном состоянии, которое, вероятно, будет редко встречаться в большинстве случаев. Это явное повышение эффективности. Как отметил Джей, лучше использовать условную логику, а не исключения, когда существует высокая вероятность отсутствия ключа. Это происходит потому, что, если ключ отсутствует в большинстве случаев, это не исключительное условие.

Тем не менее, я предлагаю вам не беспокоиться об эффективности, а скорее о значении. Используйте обработку исключений, чтобы обнаруживать исключительные случаи и проверять условия, когда вы хотите что-то решить. Мне вчера напоминали о важности значения С.Лотта.

Пример:

def xyz(key):
   dictOb = {x:1, y:2, z:3}
   #Condition evaluated every time
   if dictOb.has_key(key):  #Access 1 to dict
        print dictOb[key]  #Access 2

Против

#Exception mechanism is in play only when the key isn't found.
def xyz(key):
   dictOb = {x:1, y:2, z:3}
   try:
        print dictOb[key]  #Access 1
   except KeyError:
        print "Not Found"

В целом, имея некоторый код, который обрабатывает что-то, например, отсутствующий ключ, на всякий случай нуждается в обработке исключений, но в ситуациях, например, когда ключ больше не присутствует, что вы на самом деле хотите сделать, это решить, присутствует ли ключ = > if-else. Python подчеркивает и поощряет говорить, что вы имеете в виду.

Почему исключения предпочтительны для if-elif →

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

Примечание Когда мы избегаем использования try-except, Исключения продолжают расти. Исключения, которые не обрабатываются, просто переходят к обработчику по умолчанию. Когда вы используете try-except, вы можете самостоятельно обработать эту ошибку. Это может быть более эффективным, поскольку if-else требует оценки условий, в то время как поиск обработчика исключений может быть более дешевым. Даже если это правда, выигрыш от него будет слишком незначительным, чтобы думать о нем.

Надеюсь, мой ответ поможет.

Ответ 7

Что такое статические или динамические вызовы и возвращаемые данные, и почему вы считаете, что вызовы и возврат на Python различны в зависимости от того, выполняете ли вы это в блоке try/except? Даже если вы не поймаете исключения, Python по-прежнему должен обрабатывать вызов, возможно, что-то поднимающий, поэтому он не имеет значения для Python в отношении того, как обрабатываются вызовы и возвращает.

Каждый вызов функции в Python включает в себя толкание аргументов в стек и вызов вызываемого. Каждое завершение функции сопровождается вызывающим абонентом во внутренней проводке Python, проверяя успешное завершение или исключение и обрабатывает его соответствующим образом. Другими словами, если вы считаете, что есть некоторая дополнительная обработка, когда вы находитесь в блоке try/except, который каким-то образом пропускается, когда вы не в одном, вы ошибаетесь. Я предполагаю, что это то, что вы "статично" и "динамическое" различие было.

Кроме того, это вопрос стиля, и опытные разработчики Python приходят к тому, чтобы хорошо разбираться в исключении, так что, когда они видят соответствующий try/except вокруг вызова, он более читабельен, чем условная проверка.

Ответ 8

Общее сообщение, как сказал С.Лотт, заключается в том, что try/except не болит, поэтому вы должны свободно использовать его всякий раз, когда это кажется подходящим.

Эта дискуссия часто называется "LBYL vs. EAFP" - это "смотреть, прежде чем прыгать" против "проще просить прощения, чем разрешения". Alex Martelli весит здесь: http://mail.python.org/pipermail/python-list/2003-May/205182.html Этим дебатам почти шесть лет, но я не думаю, что основные проблемы сильно изменились.