У меня 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
, что ValueError
экземпляр не может быть вызван:
try:
do_something_that_might_raise_an_exception()
except ValueError as err:
errmsg = 'My custom error message.'
raise err(errmsg)
Ответы:
Обновление: для 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]
.Изменить: @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
источник
print
, вероятно, вы должны заметить, что ваш код не работает в Python 3.x, посколькуmessage
для исключений нет атрибута.err.args = (err.args[0] + " hello",) + err.args[1:]
может работать более надежно (а затем просто преобразовать в строку, чтобы получить сообщение)..message
атрибута здесь что-то делает, заключается в том, что этот атрибут печатается явно . Если бы вы вызывали исключение без перехвата и печати, вы бы не увидели, что.message
атрибут делает что-нибудь полезное.Если вам посчастливилось поддерживать только python 3.x, это действительно становится прекрасным :)
поднять с
Мы можем связать исключения с помощью метода raise from .
try: 1 / 0 except ZeroDivisionError as e: raise Exception('Smelly socks') from e
В этом случае исключение, которое ваш вызывающий абонент перехватит, будет иметь номер строки, в которой мы вызываем наше исключение.
Обратите внимание, что нижнее исключение имеет только трассировку стека, откуда мы подняли наше исключение. Вызывающий абонент по-прежнему может получить исходное исключение, обратившись к
__cause__
атрибуту перехваченного исключения.with_traceback
Или вы можете использовать with_traceback .
try: 1 / 0 except ZeroDivisionError as e: raise Exception('Smelly socks').with_traceback(e.__traceback__)
При использовании этой формы исключение, которое может перехватить ваш вызывающий абонент, имеет обратную связь, откуда произошла исходная ошибка.
Обратите внимание, что у нижнего исключения есть строка, в которой мы выполнили недопустимое деление, а также строка, в которой мы повторно вызываем исключение.
источник
raise Exception('Smelly socks') from e
изменить, чтобы просто добавить «Вонючие носки» в качестве комментария к исходной трассировке, а не вводить новую собственную трассировку.raise RuntimeError("Something bad happened") from None
try: try: int('a') except ValueError as e: raise ValueError('There is a problem: {0}'.format(e)) except ValueError as err: print err
печатает:
источник
raise
без параметров ререйз . Если OP хочет добавить сообщение, он должен создать новое исключение и может повторно использовать сообщение / тип исходного исключения.Похоже, все ответы добавляют информацию в 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')
Вы видите обратную сторону такого подхода?
источник
Этот шаблон кода должен позволить вам вызвать исключение с помощью настраиваемого сообщения.
try: raise ValueError except ValueError as err: raise type(err)("my message")
источник
Exception
с помощью специального сообщения в Python?» Этот отсутствие ответа вызывает новое исключение и, таким образом, вообще не дает ответа на исходный вопрос. Вот почему у нас не может быть хороших вещей.Это функция, которую я использую для изменения сообщения об исключении в Python 2.7 и 3.x с сохранением исходной трассировки. Это требует
six
def 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)
источник
six
) является EOL. Итак, это плохо. Хотя технически можно будет использовать иsix
в 2020 году, в этом нет никаких ощутимых преимуществ. Решения Pure-Python 3.x сейчас намного предпочтительнее.Текущий ответ не сработал для меня, если исключение не перехвачено повторно, добавленное сообщение не отображается.
Но выполнение приведенных ниже действий сохраняет трассировку и отображает добавленное сообщение независимо от того, перехватывается ли исключение или нет.
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)
источник
Встроенные исключения Python 3 имеют
strerror
поле:except ValueError as err: err.strerror = "New error message" raise err
источник
strerror
Переменная экземпляра является специфическим дляOSError
исключения . Поскольку для большинстваValueError
исключений эта переменная гарантированно не определяется, это нерешение обычно вызывает исключения, нечитаемые человеком, и, таким образом, является активно вредным. лол, братан.Либо вызовите новое исключение с сообщением об ошибке, используя
raise Exception('your error message')
или
raise ValueError('your error message')
в том месте, где вы хотите его поднять, ИЛИ прикрепить (заменить) сообщение об ошибке в текущее исключение, используя 'from' (поддерживается только Python 3.x):
except ValueError as e: raise ValueError('your message') from e
источник
Это работает только с Python 3 . Вы можете изменить исходные аргументы исключения и добавить свои собственные.
Исключение запоминает аргументы, с которыми оно было создано. Я предполагаю, что это сделано для того, чтобы вы могли изменить исключение.
В функции
reraise
мы добавляем к исходным аргументам исключения любые новые аргументы, которые нам нужны (например, сообщение). Наконец, мы повторно вызываем исключение, сохраняя историю трассировки.def reraise(e, *args): '''re-raise an exception with extra arguments :param e: The exception to reraise :param args: Extra args to add to the exception ''' # e.args is a tuple of arguments that the exception with instantiated with. # e.args = args + e.args # Recreate the expection and preserve the traceback info so thta we can see # where this exception originated. # raise e.with_traceback(e.__traceback__) def bad(): raise ValueError('bad') def very(): try: bad() except Exception as e: reraise(e, 'very') def very_very(): try: very() except Exception as e: reraise(e, 'very') very_very()
выход
Traceback (most recent call last): File "main.py", line 35, in <module> very_very() File "main.py", line 30, in very_very reraise(e, 'very') File "main.py", line 15, in reraise raise e.with_traceback(e.__traceback__) File "main.py", line 28, in very_very very() File "main.py", line 24, in very reraise(e, 'very') File "main.py", line 15, in reraise raise e.with_traceback(e.__traceback__) File "main.py", line 22, in very bad() File "main.py", line 18, in bad raise ValueError('bad') ValueError: ('very', 'very', 'bad')
источник
Ни одно из вышеперечисленных решений не делало именно того, что я хотел, а именно добавления некоторой информации в первую часть сообщения об ошибке, т.е. я хотел, чтобы мои пользователи сначала видели мое настраиваемое сообщение.
Это сработало для меня:
exception_raised = False try: do_something_that_might_raise_an_exception() except ValueError as e: message = str(e) exception_raised = True if exception_raised: message_to_prepend = "Custom text" raise ValueError(message_to_prepend + message)
источник
если вы хотите настроить тип ошибки, вы можете просто определить класс ошибки на основе ValueError.
источник