try tipos matrices graficos graficas graficar excepciones ejemplos diferentes coordenadas python exception numpy warnings divide-by-zero

python - tipos - ¿Cómo puedo detectar una advertencia numpy como si fuera una excepción(no solo para las pruebas)?



subplot python (4)

Elimina warnings.filterwarnings y agrega:

numpy.seterr(all=''raise'')

Tengo que hacer un polinomio de Lagrange en Python para un proyecto que estoy haciendo. Estoy haciendo un estilo baricéntrico para evitar el uso de un for-loop explícito en lugar del estilo de diferencia dividida de Newton. El problema que tengo es que necesito tomar una división por cero, pero Python (o quizás numpy) simplemente lo convierte en una advertencia en lugar de una excepción normal.

Entonces, lo que necesito saber es atrapar esta advertencia como si fuera una excepción. Las preguntas relacionadas a esto que encontré en este sitio no fueron respondidas de la manera que necesitaba. Aquí está mi código:

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.

Cuando se ejecuta este código, el resultado que obtengo es:

Warning: divide by zero encountered in int_scalars

Esa es la advertencia que quiero atrapar. Debe ocurrir dentro de la lista de comprensión.


Para agregar un poco a la respuesta de @Bakuriu:

Si ya sabe dónde es probable que ocurra la advertencia, a menudo es más limpio usar el numpy.errstate contexto numpy.errstate , en lugar de numpy.seterr que trata numpy.seterr todas las advertencias posteriores del mismo tipo, independientemente de dónde ocurran dentro de su código:

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


Para profundizar en la respuesta de @ Bakuriu anterior, he descubierto que esto me permite detectar una advertencia de tiempo de ejecución de forma similar a cómo advertiría una advertencia de error, imprimiendo la advertencia muy bien:

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

Probablemente pueda jugar con la colocación de warnings.catch_warnings () dependiendo de cuán grande sea el paraguas que quiera lanzar con los errores de captura de esta manera.


Parece que su configuración está utilizando la opción de print para 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])

Esto significa que la advertencia que ve no es una advertencia real, sino que solo se trata de algunos caracteres impresos en stdout (consulte la documentación de numpy.seterr ). Si quieres atraparlo, puedes:

  1. Use numpy.seterr(all=''raise'') que elevará directamente la excepción. Sin embargo, esto cambia el comportamiento de todas las operaciones, por lo que es un cambio bastante grande en el comportamiento.
  2. Use numpy.seterr(all=''warn'') , que transformará la advertencia impresa en una advertencia real y podrá usar la solución anterior para localizar este cambio en el comportamiento.

Una vez que tenga una advertencia, puede usar el módulo de warnings para controlar cómo se deben tratar las advertencias:

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

Lea atentamente la documentación de filterwarnings de filterwarnings ya que le permite filtrar solo la advertencia que desea y tiene otras opciones. También consideraría mirar catch_warnings que es un administrador de contexto que restablece automáticamente la función original de filterwarnings :

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