Вопрос-Ответ

What is wrong with using a bare 'except'?

Что плохого в использовании простого "except"?

Я попытался создать функцию для проверки отображения изображения на экране с помощью PyAutoGui и получил следующее:

def check_image_on_screen(image):
try:
pyautogui.locateCenterOnScreen(image)
return True
except:
return False

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

Переведено автоматически
Ответ 1

Bare except будет перехватывать исключения, которые вы почти наверняка не хотите перехватывать, включая KeyboardInterrupt (пользователь нажимает Ctrl + C) и ошибки, вызванные Python, такие как SystemExit

Если у вас нет конкретного исключения, которое вы ожидаете, по крайней мере, except Exception, которое является базовым типом для всех "обычных" исключений.


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

Перехватите все, что вы знаете, как обрабатывать, и позвольте остальным распространяться вверх по стеку вызовов, чтобы посмотреть, может ли что-то еще справиться с этим. В этом случае ошибка, которую вы ожидаете (согласно документации), является pyautogui.ImageNotFoundException

Ответ 2

По сути, вы не используете преимущества языка для поиска проблем. Если бы вы использовали except Exception as ex:, вы могли бы сделать что-то вроде регистрации исключения и точно знать, что произошло.

Ответ 3

Удаление пустого except: иногда хорошая идея, но не всегда. Остерегайтесь того, что Pycharm потеплеет по этому поводу.

PyCharm сообщает о предупреждении от pycodestyle, который не может корректно применить правило, поэтому он применяет его неправильно. Смотрите проблему: E722: (голые исключения) слишком строгие (перезапуск)

Как общее правило:


  • голое "except" для очистки - это почти всегда правильное решение, когда finally: ничего не получается.

  • простое "except" для ведения журнала часто является правильным решением, но зависит от того, хотите ли вы видеть ведение журнала преднамеренного выхода.

В обоих случаях вы ДОЛЖНЫ выполнить повторный рейз с меньшим количеством голых raise.

В PEP 8 говорится:


Предложение bare except: будет перехватывать SystemExit и KeyboardInterrupt исключения, затрудняя прерывание программы с помощью Control-C, и может замаскировать другие проблемы. Если вы хотите перехватить все исключения, которые сигнализируют об ошибках программы, используйте except Exception: (простое исключение эквивалентно except BaseException:). Хорошее эмпирическое правило - ограничивать использование простых предложений ‘except’ двумя случаями:



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

  2. Если коду нужно выполнить некоторую работу по очистке, но затем позволяет исключению распространяться вверх с помощью raise. try ...finally может быть лучшим способом справиться с этим случаем.


Общие рекомендации

Всегда повторно создавайте голое " except"

Хорошо:

try:
do_something()
except:
logging.exception("Failed")
raise

Плохо

try:
do_something()
except:
logger.exception("Failed")

💥 Это просто съело Ctrl-C или SystemExit

Убедитесь, что вы всегда выполняете очистку

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

Хорошо

file = open("my_file.txt", "w")
try:
with file:
file.write("something")
except:
os.unlink("my_file.txt")
raise

Плохо

file = open("my_file.txt", "w")
try:
with file:
file.write("something")
except Exception:
os.unlink("my_file.txt")
raise

💥 Если пользователь нажимает CTRL-C на клавиатуре в неподходящий момент, файл get остается.

python