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


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.