¿Cómo puedo incluir correctamente la syntax de excepción de Python 3.3 from None en un progtwig de Python 3.2?

Estoy intentando volver a generar una excepción para proporcionarle al usuario mejor información sobre el error real. Python 3.3 incluye PEP 409 . Agrega la syntax de la excepción raise NewException from None la raise NewException from None para suprimir el contexto de la excepción original.

Sin embargo, estoy apuntando a Python 3.2. La secuencia de comandos de Python se analizará, pero en tiempo de ejecución si encuentra la syntax de from None , producirá TypeError: exception causes must derive from BaseException . Por ejemplo:

 try: regex_c = re.compile('^{}$'.format(regex)) except re.error as e: e_msg = 'Regular expression error in "{}"'.format(regex) e_reraise = Exception(e_msg) # Makes use of the new Python 3.3 exception syntax [from None] # to suppress the context of the original exception # Causes an additional TypeError exception in Python 3.2 raise e_reraise from None 

Al encapsular el raise e_reraise from None en un try solo se obtiene una excepción de seguimiento aún mayor. Una verificación de versión tampoco funciona, ya que mi python3.3 en Xubuntu 12.10 extrae módulos de /usr/lib/python3/dist-packages/* que se configuró para los módulos de python3.2. ( Error in sys.excepthook: un Error in sys.excepthook: conveniente Error in sys.excepthook: que crea un Error in sys.excepthook: masivo ).

¿Hay alguna manera de usar la función PEP 409 cuando se ejecuta en Python 3.3, mientras se ignora silenciosamente en Python 3.2?

El PEP que has enlazado proporciona la solución:

  • raise NewException() from None

Sigue la syntax existente de declarar explícitamente la excepción de origen

  • exc = NewException(); exc.__context__ = None; raise exc

Forma muy verbosa del método anterior.

Por lo tanto, simplemente debe evitar la nueva syntax y utilizar el equivalente verboso.

Si no desea ver las asignaciones, puede poner el código en una función:

 def suppress_context(exc): exc.__context__ = None return exc 

Y luego hacer:

 raise suppress_context(TheErrorClass()) 

Edición: según lo señalado por Martijn, PEP 415 cambió este comportamiento:

Para resumir, raise exc from cause será equivalente a:

 exc.__cause__ = cause raise exc 

Por lo tanto, en lugar de configurar __context__ en None , debe establecer __cause__ en None .

Si realmente desea utilizar la nueva syntax, entonces la única forma de hacerlo es reemplazar sys.excepthook con algo que analice la salida de rastreo y elimine las partes que no desea. Pero en este caso también debes hacer esto:

 try: raise error from None except TypeError: raise error 

Luego, la excepthook debería buscar el rastreo y si debe eliminar las partes relacionadas con el raise error from None línea raise error from None . No es una tarea sencilla y terminas con más código que la otra solución.

Puede configurar exc.__cause__ = None para suprimir la impresión de contexto en Python 3.3:

 except re.error as e: e_msg = 'Regular expression error in "{}"'.format(regex) e_reraise = Exception(e_msg) e_reraise.__cause__ = None # 'raise e_reraise from None' raise e_reraise 

En Python 3.3, cuando usas raise exc from cause lo que realmente sucede es:

 exc.__cause__ = cause raise exc 

y establecer exc.__cause__ a su vez establece implícitamente exc.__suppress_context__ = True . Ver PEP 415 , que detalla cómo se maneja raise exc from None .

Cuando configuras exc.__cause__ = None en Python 3.2, nada cambia:

 $ python3.2 Python 3.2.3 (default, Apr 13 2012, 13:31:19) [GCC 4.2.1 Compatible Apple Clang 3.0 (tags/Apple/clang-211.12)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> try: ... raise ValueError() ... except: ... exc = TypeError() ... exc.__cause__ = None ... raise exc ... Traceback (most recent call last): File "", line 2, in  ValueError During handling of the above exception, another exception occurred: Traceback (most recent call last): File "", line 6, in  TypeError 

Pero en Python 3.3, el contexto se suprime en su lugar:

 $ python3.3 Python 3.3.0 (default, Sep 29 2012, 08:16:08) [GCC 4.2.1 Compatible Apple Clang 3.1 (tags/Apple/clang-318.0.58)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> try: ... raise ValueError() ... except: ... exc = TypeError() ... exc.__cause__ = None ... raise exc ... Traceback (most recent call last): File "", line 6, in  TypeError 

Al igual que si hubiera utilizado raise exc from None :

 >>> try: ... raise ValueError() ... except: ... raise TypeError() from None ... Traceback (most recent call last): File "", line 4, in  TypeError