Как создать такое же исключение с пользовательским сообщением в Python?
у меня есть это try блок в моем коде:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise ValueError(errmsg)
строго говоря, я на самом деле повышение другоеValueError, а не ValueError выдано do_something...(), которая называется err в этом случае. Как прикрепить сообщение к err? Я пробую следующий код, но не из-за err, a ValueErrorэкземпляр, не востребуемых:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise err(errmsg)
10 ответов:
обновление: для Python 3, Проверьте ответ Бена
чтобы прикрепить сообщение к текущему исключению и повторно поднять его: (внешняя попытка / исключение-это просто показать эффект)
для python 2.X, где x>=6:
try: try: raise ValueError # something bad... except ValueError as err: err.message=err.message+" hello" raise # re-raise current exception except ValueError as e: print(" got error of type "+ str(type(e))+" with message " +e.message)это тоже будет правильно если
err- это производные СValueError. НапримерUnicodeDecodeError.обратите внимание, что вы можете добавить все, что вы хотели
err. Для примерerr.problematic_array=[1,2,3].
Edit: @Ducan указывает в комментарии выше не работает с python 3 так как
.messageне является членомValueError. Вместо этого вы можете использовать это (допустимый python 2.6 или более поздней версии или 3.x):try: try: raise ValueError except ValueError as err: if not err.args: err.args=('',) err.args = err.args + ("hello",) raise except ValueError as e: print(" error was "+ str(type(e))+str(e.args))Edit2:
в зависимости от цели, вы также можете выбрать для добавления дополнительной информации под вашим собственным именем переменной. Для python2 и python3:
try: try: raise ValueError except ValueError as err: err.extra_info = "hello" raise except ValueError as e: print(" error was "+ str(type(e))+str(e)) if 'extra_info' in dir(e): print e.extra_info
Я понимаю, что этот вопрос существует уже некоторое время, но как только Вам повезет, вы сможете поддерживать только python 3.x, это действительно становится предметом красоты:)
поднять от
мы можем цепочку исключений с помощью поднять от.
try: 1 / 0 except ZeroDivisionError as e: raise Exception('Smelly socks') from eв этом случае исключение, которое ваш вызывающий абонент поймает, имеет номер строки места, где мы создаем наше исключение.
Traceback (most recent call last): File "test.py", line 2, in <module> 1 / 0 ZeroDivisionError: division by zero The above exception was the direct cause of the following exception: Traceback (most recent call last): File "test.py", line 4, in <module> raise Exception('Smelly socks') from e Exception: Smelly socksобратите внимание, что нижнее исключение имеет только stacktrace от где мы подняли наше исключение. Ваш абонент все еще может получить исходное исключение, обратившись к
__cause__атрибут исключения, которое они ловят.with_traceback
или вы можете использовать with_traceback.
try: 1 / 0 except ZeroDivisionError as e: raise Exception('Smelly socks').with_traceback(e.__traceback__)используя эту форму, исключение, которое ваш вызывающий абонент поймает, имеет обратную трассировку, откуда произошла исходная ошибка.
Traceback (most recent call last): File "test.py", line 2, in <module> 1 / 0 ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "test.py", line 4, in <module> raise Exception('Smelly socks').with_traceback(e.__traceback__) File "test.py", line 2, in <module> 1 / 0 Exception: Smelly socksобратите внимание, что в Нижнем исключении есть строка, в которой мы выполнили недопустимое деление как а также линия, где мы перезаправляем исключение.
try: try: int('a') except ValueError as e: raise ValueError('There is a problem: {0}'.format(e)) except ValueError as err: print errпринты:
There is a problem: invalid literal for int() with base 10: 'a'
Кажется, что все ответы добавляют информацию к e.args[0], тем самым изменяя существующее сообщение об ошибке. Есть ли недостаток в расширении кортежа args вместо этого? Я думаю, что возможный плюс заключается в том, что вы можете оставить исходное сообщение об ошибке в покое для случаев, когда требуется разбор этой строки; и вы можете добавить несколько элементов в кортеж, если ваша пользовательская обработка ошибок создала несколько сообщений или кодов ошибок, для случаев, когда трассировка будет анализироваться программно (например, через систему инструмент мониторинга.)
## Approach #1, if the exception may not be derived from Exception and well-behaved: def to_int(x): try: return int(x) except Exception as e: e.args = (e.args if e.args else tuple()) + ('Custom message',) raise >>> to_int('12') 12 >>> to_int('12 monkeys') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in to_int ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message')или
## Approach #2, if the exception is always derived from Exception and well-behaved: def to_int(x): try: return int(x) except Exception as e: e.args += ('Custom message',) raise >>> to_int('12') 12 >>> to_int('12 monkeys') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in to_int ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message')можете ли вы увидеть обратную сторону этого подхода?
это функция, которую я использую для изменения сообщения об исключении в Python 2.7 и 3.x при сохранении исходной обратной трассировки. Это требует
sixdef reraise_modify(caught_exc, append_msg, prepend=False): """Append message to exception while preserving attributes. Preserves exception class, and exception traceback. Note: This function needs to be called inside an except because `sys.exc_info()` requires the exception context. Args: caught_exc(Exception): The caught exception object append_msg(str): The message to append to the caught exception prepend(bool): If True prepend the message to args instead of appending Returns: None Side Effects: Re-raises the exception with the preserved data / trace but modified message """ ExceptClass = type(caught_exc) # Keep old traceback traceback = sys.exc_info()[2] if not caught_exc.args: # If no args, create our own tuple arg_list = [append_msg] else: # Take the last arg # If it is a string # append your message. # Otherwise append it to the # arg list(Not as pretty) arg_list = list(caught_exc.args[:-1]) last_arg = caught_exc.args[-1] if isinstance(last_arg, str): if prepend: arg_list.append(append_msg + last_arg) else: arg_list.append(last_arg + append_msg) else: arg_list += [last_arg, append_msg] caught_exc.args = tuple(arg_list) six.reraise(ExceptClass, caught_exc, traceback)
этот шаблон позволит вам создать исключение с настраиваемым сообщением.
try: raise ValueError except ValueError as err: raise type(err)("my message")
текущий ответ не работает хорошо для меня, если исключение не перехвачено, добавленное сообщение не отображается.
но, как показано ниже, оба сохраняют трассировку и показывают добавленное сообщение независимо от того, перехвачено ли исключение или нет.
try: raise ValueError("Original message") except ValueError as err: t, v, tb = sys.exc_info() raise t, ValueError(err.message + " Appended Info"), tb( Я использовал Python 2.7, не пробовал его в Python 3)
либо создать новое исключение с сообщением об ошибке с помощью
raise Exception('your error message')или
raise ValueError('your error message')в том месте, где вы хотите поднять его или прикрепить (заменить) сообщение об ошибке в текущее исключение с помощью 'from':
except ValueError as e: raise ValueError('your message') from e
Если вы хотите настроить тип ошибки, простая вещь, которую вы можете сделать, это определить класс ошибок на основе ValueError.
Comments