Как лучше всего получать сообщения об исключениях из компонентов стандартной библиотеки в Python?
Я заметил, что в некоторых случаях вы можете получить его через message
такое поле:
try:
pass
except Exception as ex:
print(ex.message)
но в некоторых случаях (например, в случае ошибок сокета) вам нужно сделать что-то вроде этого:
try:
pass
except socket.error as ex:
print(ex)
Мне было интересно, есть ли какой-нибудь стандартный способ охватить большинство этих ситуаций?
python
exception
exception-handling
Ледяное сердце
источник
источник
except Foo as bar:
то же самоеexcept Foo, bar:
(за исключением того, что первое новее и будет продолжать работать в 3.x), независимо от того, идет ли ошибка сmessage
атрибутом или нет, является отдельным..message
к ошибке стандартным или нет?print(msg)
- это просто ярлык дляprint(str(msg))
message
устарел.Ответы:
Если вы посмотрите документацию по встроенным ошибкам , вы увидите, что большинство
Exception
классов назначают свой первый аргумент как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)
источник
str(ex)
вместо простоex
?print()
автоматически звонитstr()
вам. Нет причин вызывать его вручную, хотя это безвредно, поскольку вызовstr()
строки просто вернет саму строку.str()
типом сообщенияunicode
.Чтобы улучшить ответ, предоставленный @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
источник
getattr
генерирует исключение, если переданный объект не имеет запрошенного атрибута. Если вы хотите сделать что - то подобное, я думаю , вы должны использовать необязательный третий аргумент в пользуgetattr
, например:print getattr(e, 'message', e)
. Сомнительно лучше, чем то, что я сделал. Другой вариант был быprint(e.message if hasattr(e, 'message') else e)
.str
вместоrepr
.str
,repr
просто добавляет имя класса. Вместо использованияrepr
предлагаю использоватьprint('{e.__class__.__name__}: {e}'.format(e=e))
. Вывод на печать чище и соответствует выводу самого повышения.'{e.__class__.__module__}.{e.__class__.__name__}: {e}'
repr(e)
на данный момент было единственным решением, которое помогло мне напечатать хотя бы минимальный объем информации об ошибке, которую я улавливаю в определенных обстоятельствах.repr(e)
даетKeyError(0,)
(что и является ошибкой), в то время какstr(e)
илиe.message
дает только0
или вообще ничего, соответственно.У меня такая же проблема. Я думаю, что лучшим решением является использование log.exception, который автоматически распечатает трассировку стека и сообщение об ошибке, например:
try: pass log.info('Success') except: log.exception('Failed')
источник
log
? Я только что попробовалimport log
Python 2.7.13 и получил сообщение о том, что модуля с таким именем нет. Это что-то, что вы добавили через,pip
или это было добавлено в более новую версию python (я знаю, я знаю, мне нужно обновить до Python 3 ... Я сделаю это, как только CentOS перестанет поставляться с Python 2 по умолчанию ...)import logging
\ nlog = logging.getLogger(__name__)
У меня тоже была такая же проблема. Вникнув в это, я обнаружил, что класс Exception имеет
args
атрибут, который фиксирует аргументы, которые использовались для создания исключения. Если вы сузите исключения, которые, кроме того, будут улавливаться, до подмножества, вы сможете определить, как они были созданы, и, следовательно, какой аргумент содержит сообщение.try: # do something that may raise an AuthException except AuthException as ex: if ex.args[0] == "Authentication Timeout.": # handle timeout else: # generic handling
источник