Devolviendo una cadena de error desde una función en Python

Tengo una función de clase en Python que devuelve un éxito o una falla, pero en caso de una falla, quiero que envíe una cadena de error específica. Tengo 3 enfoques en mente:

  1. Pase una variable error_msg a la función establecida originalmente en Ninguno y, en caso de error, se establece en la cadena de error. p.ej:

    if !(foo(self, input, error_msg)): print "no error" else: print error_msg 
  2. Devuelve una tupla que contiene un bool y error_msg de la función.

  3. Levanto una excepción en caso de error y la detecto en el código de llamada. Pero como no veo que se usen a menudo las excepciones en el código base en el que estoy trabajando, no estaba tan seguro de adoptar este enfoque.

¿Cuál es la forma pythonica de hacer esto?

Crea tu propia excepción y levántala en su lugar:

 class MyValidationError(Exception): pass def my_function(): if not foo(): raise MyValidationError("Error message") return 4 

A continuación, puede llamar a su función como:

 try: result = my_function() except MyValidationError as exception: # handle exception here and get error message print exception.message 

Este estilo se llama EAFP (“Es más fácil pedir perdón que permiso”), lo que significa que escribe el código normalmente, genera excepciones cuando algo sale mal y lo maneja más adelante:

Este estilo de encoding de Python común asume la existencia de claves o atributos válidos y detecta excepciones si la suposición es falsa. Este estilo limpio y rápido se caracteriza por la presencia de muchas declaraciones try y except. La técnica contrasta con el estilo LBYL común a muchos otros idiomas, como C.

Levantar un error:

 if foo(self, input, error_msg): raise SomethingError("You broke it") 

Y manejarlo:

 try: something() except SomethingError as e: print str(e) 

Es el enfoque pythonico y el más legible.

Devolver una tupla como (12, None) puede parecer una buena solución, pero es difícil hacer un seguimiento de lo que devuelve cada método si no eres consistente. Devolver dos tipos de datos diferentes es aún peor, ya que probablemente romperá el código que asume un tipo de datos constante.