파이썬에서 예외 인 것처럼 경고를 어떻게 포착합니까?


103

파이썬 코드에서 사용하는 타사 라이브러리 (C로 작성)가 경고를 발행합니다. try except구문을 사용하여 이러한 경고를 올바르게 처리 할 수 있기를 원합니다 . 이 작업을 수행하는 방법이 있습니까?


2
그 경고는 문자 메시지가 stderr로 작성됩니까?
Fenikso 2011

1
Fenikso : 나는 확실히 모르는, 진짜 경고처럼 보인다
보리스 Gorelik

1
"진짜 경고"를 어떻게 인식합니까? 나는 C에서 컴파일하는 동안 진짜 경고를받는다고 생각했습니다.
Fenikso 2011

warnings.filterwarnings당신이 원하는 것이 정확히 무엇인지, 나는 그것에 대한 당신의 문제가 무엇인지 이해하지 못합니까?
Rosh Oxymoron 2011

4
@Fenikso, @Rosh Oxymoron 당신이 옳았습니다. 내 실수. warnings.filterwarnigns('error')일을합니다. 나는이 솔루션을 제안 원래 답변을 찾을 수 없습니다
보리스 Gorelik

답변:


51

파이썬 핸드북 ( 27.6.4. 경고 테스트 ) 에서 인용하려면 :

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings(record=True) as w:
    # Cause all warnings to always be triggered.
    warnings.simplefilter("always")
    # Trigger a warning.
    fxn()
    # Verify some things
    assert len(w) == 1
    assert issubclass(w[-1].category, DeprecationWarning)
    assert "deprecated" in str(w[-1].message)

6
여기에 대한 답은이 방법을 사용하는 방법을 알 수있다 try except구.
Unapiedra

이것은 niekas의 대답보다 이점이 있습니다. fnx무언가를 반환하면 그 결과를 유지하고 여전히 경고를 관리 할 수 ​​있습니다.
Pietro Battiston

이것은 그들을 테스트하는 것이 아니라 흔들리는 것을 처리하는 것에 관한 OP의 질문에 대답하지 않습니다. 그러나 아래 niekas의 대답은 경고를 처리하는 방법을 보여줍니다.
Biggsy

위의 함수는 경고를 반환 fxn()하지 않는 w경우 빈 목록이 되기 때문에 함수가 간헐적으로 경고를 반환하는 경우에만 작동 하지 않습니다 . 경우 w빈리스트 (예입니다 []), 다음 코드를 실행하는 것은 당신에게 다음과 같은 오류를 제공합니다 IndexError: list index out of range. 캡처 된 경고의 속성을 형식화하거나 확인하려는 경우 for 루프를 사용하는 것이 좋습니다.for x in w: print(f'{x.category.__name__}: {str(x.message)}')
Steven M. Mortimer

130

경고를 오류로 처리하려면 다음을 사용하십시오.

import warnings
warnings.filterwarnings("error")

그런 다음 오류와 동일한 경고를 포착 할 수 있습니다. 예를 들어 다음과 같이 작동합니다.

try:
    some_heavy_calculations()
except RuntimeWarning:
    import ipdb; ipdb.set_trace()

의견의 가장 좋은 대답이 오자 포함하기 때문에 PS는이 대답을 추가 : filterwarnigns대신 filterwarnings.


8
스택 추적 만보고 싶다면 처음 두 줄만 있으면됩니다.
z0r

5
이것은 완벽 해요. 경고가 발생하자마자 스크립트 실행을 중지하여 관련 디버그 정보를 인쇄하고 문제를 해결할 수 있기를 원했습니다.
Praveen

1
적어도 파이썬 3에서는 filterwarnings을 잡기 위해 호출이 필요하지 않습니다 Warnings.
naught101

1
수락 된 답변은 OP의 질문에 대한 답변이 아닙니다. 이 대답은 그렇습니다. 이 질문을 검색했을 때 찾고 있던 답변입니다.
Biggsy


15

다음은 사용자 지정 경고 만 사용하는 방법을 더 명확하게하는 변형입니다.

import warnings
with warnings.catch_warnings(record=True) as w:
    # Cause all warnings to always be triggered.
    warnings.simplefilter("always")

    # Call some code that triggers a custom warning.
    functionThatRaisesWarning()

    # ignore any non-custom warnings that may be in the list
    w = filter(lambda i: issubclass(i.category, UserWarning), w)

    if len(w):
        # do something with the first warning
        email_admins(w[0].message)

4

어떤 경우에는 경고를 오류로 전환하기 위해 ctypes를 사용해야합니다. 예를 들면 :

str(b'test')  # no error
import warnings
warnings.simplefilter('error', BytesWarning)
str(b'test')  # still no error
import ctypes
ctypes.c_int.in_dll(ctypes.pythonapi, 'Py_BytesWarningFlag').value = 2
str(b'test')  # this raises an error

이 대답은 특정 경고 유형에서만 오류를 일으키는 방법을 보여주기 위해 건설적입니다. 거의 모든 대규모 소프트웨어 프로젝트의 경우 warnings.simplefilter('error')로그에서 본 경고에 대한 트레이스 백을 얻지 못하고 대신 이전에 필터링 된 경고에서 트레이스 백을 얻습니다. simplefilterCLI 호출이있는 경우 사용하는 것이 가장 빠른 방법입니다.
AlanSE
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.