source

Python에서 커스텀 메시지와 동일한 예외를 발생시키는 방법은 무엇입니까?

lovecheck 2022. 10. 20. 21:57
반응형

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,aValueError 인스턴스, 호출할 수 없음:

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

운이 좋아서 python 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_syslogback

또는 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

아래쪽 예외에는 비활성 분할을 수행한 행과 예외를 다시 발생시킨 행이 있습니다.

업데이트: 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)

또, 이 방법은, 만약 이 데이터로부터 파생된 이라면, 올바른 을 할 것입니다.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))

편집 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

모든 답변이 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:
    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'

이것은 Python 3에서만 동작합니다.예외의 원래 인수를 수정하고 고유한 인수를 추가할 수 있습니다.

예외는 작성된 Arg를 기억합니다.이것은 당신이 예외를 수정할 수 있도록 하기 위한 것이라고 생각합니다.

'''에서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')

이 코드 템플릿을 사용하면 커스텀메시지로 예외를 발생시킬 수 있습니다.

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에서 예외 메시지를 수정하기 위해 사용하는 기능입니다.그것은 필요하다

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)

현재 답변이 잘 작동하지 않습니다. 예외를 다시 포착하지 않으면 첨부된 메시지가 표시되지 않습니다.

그러나 다음과 같이 하면 예외 재캐치 여부에 관계없이 모두 트레이스가 유지되고 추가된 메시지가 표시됩니다.

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

위의 어느 솔루션도 원하는 대로 되지 않았습니다.즉, 에러 메시지의 첫 부분에 정보를 추가하는 것입니다.사용자 지정 메시지를 먼저 볼 수 있도록 했습니다.

이 방법은 효과가 있었습니다.

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)

아래 시도:

try:
    raise ValueError("Original message. ")
except Exception as err:
    message = 'My custom error message. '
    # Change the order below to "(message + str(err),)" if custom message is needed first. 
    err.args = (str(err) + message,)
    raise 

출력:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
      1 try:
----> 2     raise ValueError("Original message")
      3 except Exception as err:
      4     message = 'My custom error message.'
      5     err.args = (str(err) + ". " + message,)

ValueError: Original message. My custom error message.

이 컴팩트한 버전의 @RobinL을 사용해 보고, 작업도 했습니다.

try:
    do_something_that_might_raise_an_exception()
except ValueError as e:
    raise ValueError(f'Custom text {e}')

제안된 솔루션 중 많은 부분이 예외를 다시 제기하는 것으로, 이는 잘못된 관행으로 간주됩니다.이렇게 간단한 걸로 충분할 거야

try:
    import settings
except ModuleNotFoundError:
    print("Something meaningfull\n")
    raise 

따라서 오류 메시지를 먼저 인쇄한 후 스택 트레이스를 올리거나 sys.exit(1)을 사용하여 종료하고 오류 메시지를 전혀 표시하지 않습니다.

에러 타입을 커스터마이즈 하는 경우는, ValueError 에 근거해 에러 클래스를 정의할 수 있습니다.

언급URL : https://stackoverflow.com/questions/9157210/how-do-i-raise-the-same-exception-with-a-custom-message-in-python

반응형