2010-03-26 6 views
19

¿Cuál es la forma correcta de hacer la comprobación de errores en una clase? ¿Planteando excepciones? Establecer un diccionario de variables de instancia "errores" que contiene todos los errores y devolverlos?Manera adecuada en Python para generar errores al establecer las variables

¿Es malo imprimir los errores de una clase? ¿Debo devolver False si presento una excepción?

Solo quiero asegurarme de estar haciendo las cosas bien. A continuación se muestra un código de ejemplo:

@property 
def password(self): 
    return self._password 

@password.setter 
def password(self,password): 
    # Check that password has been completed 
    try: 
     # Check that password has a length of 6 characters 
     if (len(password) < 6): 
      raise NameError('Your password must be greater \ 
          than 6 characters') 

    except NameError: 
     print 'Please choose a password' 
     return False 

    except TypeError: 
     print 'Please choose a password' 
     return False                                 

    #Set the password 
    self._password = password 

    #Encrypt the password 
    password_md5 = md5.new() 
    password_md5.update(password) 
    self._password_md5 = password_md5.hexdigest() 
+1

Demasiadas cosas llamadas 'contraseña' en ese código. (la primera función, la segunda función y el argumento para la segunda función.) pyflakes será tu amigo. – keturn

+0

@keturn: es un patrón que se muestra en los documentos para la función 'property()'. Mire el [ejemplo de código en los documentos que usa el decorador '.setter'] (https://docs.python.org/3/library/functions.html#property). Dentro del método setter 'contraseña' es una variable local (parámetro). Otros nombres están en un espacio de nombre diferente (pertenecen a la clase). – jfs

Respuesta

28

Su código está fuera de contexto, por lo que no es obvio que sea la elección correcta.Siguiendo algunos consejos:

  • No utilice NameError excepción, sólo se utiliza cuando un nombre, como la excepción en sí Dicho esto, no se encuentra en el ámbito local o global, utilice ValueError o TypeError si las preocupaciones de excepción el valor o el tipo del parámetro;

  • No imprimir mensajes de error. Elevar excepciones significativas con un mensaje de error significativo:

    raise ValueError("password must be longer than 6 characters") 
    
  • Volviendo un valor de un setter tiene sentido mientras asignación no es una expresión, es decir, no se puede comprobar el valor de una asignación:

    if (user.password = 'short'): ... 
    
  • Simplemente levante una excepción en el colocador y deje que el código que establece la propiedad lo maneje.

Ejemplo:

class Test: 

    minlen = 6 

    @property 
    def password(self): 
     return self._password 

    @password.setter 
    def password(self, value): 
     if not isinstance(value, basestring): 
      raise TypeError("password must be a string") 
     if len(value) < self.minlen: 
      raise ValueError("password must be at least %d character len" % \ 
           self.minlen) 
     self._password = value 

mirar también a this forms handling library, no los validadores, here an example, son entidades en su propia: que se pueden ajustar de forma dinámica con un mayor control y código de menos acoplada, pero tal vez esto es mucho más de lo que necesitas

+1

Esto fue realmente útil. Gracias. – ensnare

+0

@mg, Excelente publicación (¡y excelentes iniciales!) En general, pero me preocupa el ejemplo al final. Pareces haber inventado un decorador de 'contraseña', cuyo uso es bastante extraño; ¿Quiere decir '@ property' y nombrar el primer método' password'? Además, deberá usar clases de estilo nuevo si desea usar propiedades, es decir, cambiar la primera línea del ejemplo a 'clase Prueba (objeto):' o heredar de alguna otra clase de estilo nuevo. (Incluso si no estuviera usando propiedades todavía, debe usar clases de estilo nuevo.) –

+0

@Mike Graham: Maldita sea, el cansancio podría hacer bromas pesadas. tienes razón para el nombre de la propiedad, la forma exacta es la utilizada originalmente por ensare, prefiero la antigua buena 'contraseña = propiedad (...)' pero sería coherente con ensare sin conocer realmente la nueva sintaxis 2.6. La segunda observación no es verdadera: las propiedades se pueden usar con las antiguas clases de estilo –

10

La forma estándar de señalización de un error en Python es elevar una excepción y permitir que el mango código de llamada es. O permite que NameError & TypeError continúe hacia arriba, o que los capture y genere una excepción InvalidPassword que defina.

Si bien es posible devolver un indicador de éxito/falla o un código de error de la función como lo ha hecho, no se recomienda - es fácil que la persona que llama olvide verificar el valor de retorno y perder los errores. Además de devolver un valor de un conjunto de propiedades, esto no tiene sentido en Python ya que las asignaciones no son expresiones y no pueden devolver un valor.

Además, nunca debe imprimir un mensaje para el usuario en su manejo de excepciones. ¿Qué ocurre si luego desea utilizar la función o clase en un programa GUI? En ese caso, su extracto impreso no tendrá dónde imprimir. Sin embargo, registrar un error en un archivo de registro (usando el módulo de registro de Python) a menudo es útil para la depuración.

4

Generalmente, debe indicar los errores que se propagan mediante el uso de excepciones. Si descubre un error por algo que acaba de verificar y puede resolverlo de inmediato, no es necesario hacer una excepción.

En el caso particular de un colocador, por ejemplo, devolver False o cualquier otra cosa no ayudará. Establecer las variables de instancia que debe verificar es muy poco óptimo, ya que entonces podría perder un error por accidente.

print generalmente no es una buena respuesta a un error. En este caso, parece que desea decirle al usuario final que necesita usar una contraseña diferente. Parece que debe llamar a un método que causa que la página web con el formulario explique al usuario qué fue lo que salió mal; podría llamar al método que hace eso en su clase o plantear una excepción que se propagará y eventualmente será capturada y utilizada para ese propósito. (Este es un consejo general. No sé lo suficiente sobre Pilones para decirle cómo desea que haga esto).

No debe plantear sus propias excepciones NameError. NameError prettymuch siempre indica un error tipográfico en su programa, y ​​como tal, por lo general no desea atraparlo. Al atraparlo, introduce incertidumbre innecesaria en un programa. Parece que podría ser algo más como ValueError o una subclase de la misma (class InvalidPasswordError(ValueError): pass).

No entiendo por qué marque TypeError. Siempre debes entender qué habría causado una excepción que capturaste. Si lo haces en este caso, eso es genial; No puedo entender qué error aumentaría el TypeError con el que podría lidiar de manera sensata al preguntar al usuario.

Su técnica para recibir la contraseña en texto plano y almacenar su hash md5 no es muy segura. Debería buscar algo como AuthKit que podría hacer que este proceso sea más seguro y abstracto.

Cuestiones relacionadas