복붙노트

[PYTHON] 예외 (테스트 만)가 아닌 것처럼 numpy 경고를 어떻게 catch합니까?

PYTHON

예외 (테스트 만)가 아닌 것처럼 numpy 경고를 어떻게 catch합니까?

내가하고있는 프로젝트를 위해 Python에서 Lagrange 다항식을 만들어야합니다. 저는 뉴턴의 분할 된 차이 스타일과는 달리 명시적인 for-loop를 사용하지 않으려 고하는 중력 스타일을하고 있습니다. 내가 가진 문제는 0으로 나눗셈을 잡아야한다는 것이지만, 파이썬 (또는 아마 numpy)은 보통의 예외 대신에 경고를 만들어 낸다.

그래서 내가 어떻게해야하는지 알 필요가있는 것은이 경고를 예외 인 것처럼 잡는 것입니다. 이 사이트에서 발견 된 관련 질문은 내가 필요한 방식으로 답변되지 않았습니다. 내 코드는 다음과 같습니다.

import numpy as np
import matplotlib.pyplot as plt
import warnings

class Lagrange:
    def __init__(self, xPts, yPts):
        self.xPts = np.array(xPts)
        self.yPts = np.array(yPts)
        self.degree = len(xPts)-1 
        self.weights = np.array([np.product([x_j - x_i for x_j in xPts if x_j != x_i]) for x_i in xPts])

    def __call__(self, x):
        warnings.filterwarnings("error")
        try:
            bigNumerator = np.product(x - self.xPts)
            numerators = np.array([bigNumerator/(x - x_j) for x_j in self.xPts])
            return sum(numerators/self.weights*self.yPts) 
        except Exception, e: # Catch division by 0. Only possible in 'numerators' array
            return yPts[np.where(xPts == x)[0][0]]

L = Lagrange([-1,0,1],[1,0,1]) # Creates quadratic poly L(x) = x^2

L(1) # This should catch an error, then return 1. 

이 코드가 실행되면 얻을 수있는 결과는 다음과 같습니다.

Warning: divide by zero encountered in int_scalars

그것이 내가 잡으려고하는 경고입니다. 그것은 목록 이해력 내에서 발생해야합니다.

해결법

  1. ==============================

    1.귀하의 구성이 numpy.seterr에 대한 인쇄 옵션을 사용하고있는 것 같습니다 :

    귀하의 구성이 numpy.seterr에 대한 인쇄 옵션을 사용하고있는 것 같습니다 :

    >>> import numpy as np
    >>> np.array([1])/0   #'warn' mode
    __main__:1: RuntimeWarning: divide by zero encountered in divide
    array([0])
    >>> np.seterr(all='print')
    {'over': 'warn', 'divide': 'warn', 'invalid': 'warn', 'under': 'ignore'}
    >>> np.array([1])/0   #'print' mode
    Warning: divide by zero encountered in divide
    array([0])
    

    즉, 경고 메시지는 실제 경고가 아니지만 stdout에 인쇄 된 문자 중 일부일뿐입니다 (seterr 설명서 참조). 그것을 잡으려면 다음을 할 수 있습니다.

    실제로 경고가 발생하면 경고 모듈을 사용하여 경고를 처리하는 방법을 제어 할 수 있습니다.

    >>> import warnings
    >>> 
    >>> warnings.filterwarnings('error')
    >>> 
    >>> try:
    ...     warnings.warn(Warning())
    ... except Warning:
    ...     print 'Warning was raised as an exception!'
    ... 
    Warning was raised as an exception!
    

    filterwarnings에 대한 설명서를주의 깊게 읽으십시오. 원하는 경고 만 필터링하고 다른 옵션을 사용할 수 있기 때문입니다. 또한 원래 filterwarnings 함수를 자동으로 다시 설정하는 컨텍스트 관리자 인 catch_warnings을 살펴 보겠습니다.

    >>> import warnings
    >>> with warnings.catch_warnings():
    ...     warnings.filterwarnings('error')
    ...     try:
    ...         warnings.warn(Warning())
    ...     except Warning: print 'Raised!'
    ... 
    Raised!
    >>> try:
    ...     warnings.warn(Warning())
    ... except Warning: print 'Not raised!'
    ... 
    __main__:2: Warning: 
    
  2. ==============================

    2.@ Bakuriu의 답변에 약간을 추가하려면 다음을 수행하십시오.

    @ Bakuriu의 답변에 약간을 추가하려면 다음을 수행하십시오.

    이미 어디에서 경고가 발생하는지 알고 있다면 numpy.errstate 컨텍스트 관리자를 사용하는 것이 더 깨끗합니다. numpy.seterr는 코드 내에서 발생하는 위치에 관계없이 동일한 유형의 모든 후속 경고를 동일하게 처리합니다.

    import numpy as np
    
    a = np.r_[0]
    with np.errstate(divide='raise'):
        try:
            a / 0   # this gets caught and handled as an exception
        except FloatingPointError:
            print('oh no!')
    a / 0           # this prints a RuntimeWarning as usual 
    
  3. ==============================

    3.위의 @ Bakuriu의 대답에 대해 자세히 설명하기 위해이 방법을 사용하면 오류 경고를 잡아 내고 멋지게 경고를 출력하는 것과 비슷한 방식으로 런타임 경고를 잡을 수 있습니다.

    위의 @ Bakuriu의 대답에 대해 자세히 설명하기 위해이 방법을 사용하면 오류 경고를 잡아 내고 멋지게 경고를 출력하는 것과 비슷한 방식으로 런타임 경고를 잡을 수 있습니다.

    import warnings
    
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        try:
            answer = 1 / 0
        except Warning as e:
            print('error found:', e)
    

    이런 식으로 잡기 오류로 캐스팅하려는 우산의 크기에 따라 warnings.catch_warnings () 배치를 배치하는 것으로 놀 수도 있습니다.

  4. ==============================

    4.warnings.filterwarnings을 삭제하고 다음을 추가하십시오.

    warnings.filterwarnings을 삭제하고 다음을 추가하십시오.

    numpy.seterr(all='raise')
    
  5. from https://stackoverflow.com/questions/15933741/how-do-i-catch-a-numpy-warning-like-its-an-exception-not-just-for-testing by cc-by-sa and MIT license