[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어떻게 첨부 합니까? 나는 다음과 같은 코드를 시도하지만 인해 실패 errA, ValueError , 호출되지 않는 :

try:
    do_something_that_might_raise_an_exception()
except ValueError as err:
    errmsg = 'My custom error message.'
    raise err(errmsg)



답변

업데이트 : Python 3의 경우 Ben의 답변을 확인하십시오.


현재 예외에 메시지를 첨부하고 다시 올리려면 다음을 수행하십시오.

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의 멤버가 아니기 때문에 위의 python 3에서는 작동하지 않습니다 ValueError. 대신 이것을 사용할 수 있습니다 (유효한 파이썬 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))

편집 2 :

목적이 무엇인지에 따라 변수 이름 아래에 추가 정보를 추가하도록 선택할 수도 있습니다. 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


답변

파이썬 3.x 만 지원할만큼 운이 좋으면 이것이 정말 아름다움이됩니다 🙂

에서 올리다

raise from을 사용하여 예외를 연결할 수 있습니다 .

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

맨 아래 예외에는 예외를 발생시킨 지점의 스택 추적 만 있습니다. 발신자는 여전히 예외 예외의 __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')

이 접근법의 단점을 볼 수 있습니까?


답변

이 코드 템플릿을 사용하면 사용자 정의 메시지로 예외를 제기 할 수 있습니다.

try:
     raise ValueError
except ValueError as err:
    raise type(err)("my message")


답변

다음을 사용하여 오류 메시지와 함께 새로운 예외를 제기하십시오.

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 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)