Подтвердить что ты не робот

Как правильно получить сообщение об исключении в Python

Каков наилучший способ получить сообщения исключений из компонентов стандартной библиотеки в Python?

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

try:
  pass
except Exception as ex:
  print(ex.message)

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

try:
  pass
except socket.error as ex:
  print(ex)

Я задавался вопросом, есть ли стандартный способ охватить большинство этих ситуаций?

4b9b3361

Ответ 1

Если вы посмотрите на документацию для встроенных ошибок, вы увидите, что большинство классов Exception назначают свой первый аргумент как a message. Не все из них, хотя.

Примечательно, что EnvironmentError (с подклассами IOError и OSError) имеет первый аргумент errno, второй из strerror. Нет message... strerror примерно аналогично тому, что обычно было бы message.

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

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

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

Вы также можете проверить атрибут сообщения, если хотите, например, но я бы не предложил его, поскольку он просто кажется беспорядочным:

try:
    pass
except Exception as e:
    # Just print(e) is cleaner and more likely what you want,
    # but if you insist on printing message specifically whenever possible...
    if hasattr(e, 'message'):
        print(e.message)
    else:
        print(e)

Ответ 2

Чтобы улучшить ответ, предоставляемый @artofwarfare, вот что я считаю более удобным способом проверить атрибут message и распечатать его или распечатать объект Exception в качестве запасного варианта.

try:
    pass 
except Exception as e:
    print getattr(e, 'message', repr(e))

Вызов repr не обязателен, но я считаю его необходимым в некоторых случаях.


Обновление № 1:

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

try:
    raise Exception 
except Exception as e:
    print(getattr(e, 'message', repr(e)))
    print(getattr(e, 'message', str(e)))

Обновление № 2:

Вот демонстрационная версия со спецификой для Python 2.7 и 3.5: https://gist.github.com/takwas/3b7a6edddef783f2abddffda1439f533

Ответ 3

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

try:
    pass
    log.info('Success')
except:
    log.exception('Failed')