2012-04-25 12 views
9

Pregunta básica: ¿Cuál es la forma más lógica y pitónica de crear mis propias clases de advertencia personalizadas? ¿Cuáles son las clases correctas de advertencia y excepción que debería estar subclasificando?Advertencias Pythonic, personalizadas

motivación: Los requisitos para la biblioteca que estoy escribiendo especifica que si un objeto cMyContainer contiene un elemento x y el llamador de la biblioteca intenta colocar un "duplicado" de x - llamarlo y - en c, se emite una advertencia a la persona que llama y el valor de retorno de c.my_transformation_method(x, y) se coloca en c para reemplazar x. En otras palabras, MyContainer s reemplazará los elementos con sus duplicados, pero debe advertir al usuario al hacerlo.

Según mis lecturas, la forma más flexible de advertir a la persona que llama de una biblioteca sobre una acción no fatal es con el warnings standard module. Permite que la persona que llama maneje la advertencia como lo considere conveniente, haciendo cualquier cosa, desde ignorar las advertencias hasta tratarlas como errores. (Tenga en cuenta que estoy usando Python 3, pero no creo que eso es esencial para la cuestión aquí.)

Ejemplo: Lo que he hecho se define de la siguiente subclase advertencia:

class DuplicateItemWarning(UserWarning, ValueError): 
    pass 

Luego, el método add() de MyContainer llama al warnings.warn('detected duplicate', DuplicateItemWarning) cuando detecta un intento de insertar un elemento duplicado.

preguntas específicas:

  1. ¿Debo subclassing UserWarning que el anterior, o simplemente sublcassing Warning?

  2. Parece sensato semánticamente subclase ValueError (que, en el ejemplo anterior, simplemente inserta ValueError en el MRO entre Warning y Exception) en el caso de una persona que llama quiere tratar a los avisos como errores. ¿Hay algún inconveniente en esto que no estoy viendo?

  3. No pude encontrar ninguna pregunta previa sobre StackOverflow sobre la personalización de clases de advertencia. ¿Esto es porque los programadores de Python ni siquiera les gusta usar el módulo warnings?

+0

IMO, el enfoque más pitónico es simplemente usar las advertencias y excepciones incorporadas, proporcionando su propio mensaje. ¿Cuál es el caso para la subclasificación? – Wilduck

+0

@Wilduck Quizás necesite crear otros tipos de advertencias para esta biblioteca, pero también me gusta la semántica de tener una advertencia que también es un 'ValueError'. En cualquier caso, ¿cuál es la advertencia incorporada correcta para usar en esta situación? '¿Advertencia? 'UserWarning'? – wkschwartz

+0

Creo que ciertamente no es 'Advertencia'. Es la clase base de todas las advertencias. Consulte http://docs.python.org/py3k/library/warnings.html#warning-categories para obtener una lista completa, depende de lo que su advertencia debería significar – jadkik94

Respuesta

4

Después de leer el PEP 230 sobre el marco de aviso y la documentación de las advertencias, creo que tengo la respuesta a sus preguntas:

  1. UserWarning y todos los demás están advirtiendo categorías, que no parecen tener otro rol además de la clasificación. De esta forma, podría filtrarlos en su entorno de producción, por ejemplo. Entonces, básicamente, podría subclasificar desde Warning si la advertencia no cae en ninguna otra categoría. Si en el contexto, UserWarning o RuntimeWarning parece suficiente, solo úselos.

  2. Warning s ya son Exception s.Por lo tanto, técnicamente, para "atraparlos" como errores, solo necesita cambiar el filtro, no es necesario crear una subclase desde XXXError. Ahora, de nuevo, todo tiene sentido. Si las advertencias son acerca de los valores pasados, puede crear una subclase de ValueError, especialmente si hubiera muchas advertencias personalizadas diferentes, es de esperar que el llamante "atrape" todas las advertencias sobre los valores de una sola vez.

    try: 
        # do something 
    except MyCustomWarningOne: 
        # do something else 
    except MyCustomWarningTwo: 
        # do something else also 
    except ValueError: # or RuntimeWarning if you subclass from it 
        # catch some other warning (both of these subclass from ValueError for example) 
    
  3. El módulo warnings es la idea de Guido van Rossum. (Ver PEP 230). Si eso no es lo suficientemente pitónico ...: D

+1

Entonces, si te entiendo correctamente, mi enfoque de subclases es bueno siempre que eso haga que mis advertencias tengan el sentido más intuitivo para los usuarios. Evitar la creación de subclases, _i.e._, utilizando 'RuntimeWarning' directamente (' UserWarning' parece una excepción, ya que su nombre es tan inespecífico) es bueno cuando mi biblioteca no tiene muchas advertencias diferentes para dar. ¿Es esto correcto? – wkschwartz

+0

Sí, eso es lo que quiero decir. Creo que tiene sentido hacerlo, pero no puedo garantizar que esta sea la forma en que debes hacerlo. Ver otras opiniones también :) – jadkik94

+0

Usar 'Advertencia' como la clase base y el mencionado * filtrado * significa que puede capturar fácilmente + informar + ignorar todas las advertencias en la cláusula' excepto Advertencia como advertencia: ', incluidas las que usted hizo no inventado – pepr