¿Sintaxis válida en Python 2.xy 3.x para generar una excepción?

¿Cómo puedo portar este código a Python 3 para que se ejecute tanto en Python 2 como en Python3?

raise BarException, BarException(e), sys.exc_info()[2] 

(Copiado de http://blog.ionelmc.ro/2014/08/03/the-most-underrated-feature-in-python-3/ )

Pregunta extra
¿Tiene sentido hacer algo como

 IS_PYTHON2 = sys.version_info < (3, 0) if IS_PYTHON2: raise BarException, BarException(e), sys.exc_info()[2] # replace with the code that would run in Python 2 and Python 3 respectively else: raise BarException("Bar is closed on Christmas") 

Tendrá que recurrir al uso de exec() porque no puede usar la syntax de 3 argumentos en Python 3; generará un error de syntax.

Como siempre, las six bibliotecas ya lo tienen cubierto, para no depender de otras six definiciones, su versión tiene este aspecto:

 import sys if sys.version_info[0] == 3: def reraise(tp, value, tb=None): if value is None: value = tp() if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value else: exec("def reraise(tp, value, tb=None):\n raise tp, value, tb\n") 

Ahora puedes usar:

 reraise(BarException, BarException(e), sys.exc_info()[2]) 

sin más pruebas para una versión de Python.

Código compatible con Python 2/3 para generar una excepción

Six proporciona utilidades sencillas para resolver las diferencias entre Python 2 y Python 3. Está diseñado para admitir bases de código que funcionan tanto en Python 2 como en 3 sin modificaciones. seis consta de un solo archivo de Python, por lo que es fácil copiar en un proyecto. http://pythonhosted.org/six/

 from six import reraise as raise_ # or from future.utils import raise_ traceback = sys.exc_info()[2] err_msg = "Bar is closed on Christmas" raise_(ValueError, err_msg, traceback) 

Conversión de Python 2 a Python 3.

Puedes hacer una copia de Python 3 del código usando 2to3.

2to3 es un progtwig de Python que lee el código fuente de Python 2.x y aplica una serie de fijadores para transformarlo en un código de Python 3.x válido. La biblioteca estándar contiene un rico conjunto de fijadores que manejarán casi todo el código. Sin embargo, 2to3 que soporta la biblioteca lib2to3 es una biblioteca flexible y genérica, por lo que es posible escribir sus propios fijadores para 2to3. lib2to3 también podría adaptarse a aplicaciones personalizadas en las que el código de Python debe editarse automáticamente.

2to3 también puede escribir las modificaciones necesarias de nuevo en el archivo fuente. (Por supuesto, también se puede hacer una copia de seguridad del original a menos que también se proporcione -n). La escritura de los cambios se habilita con la marca -w:

 $ 2to3 -w example.py 

(de https://docs.python.org/3.0/library/2to3.html )

Determinación de la versión de Python

Si quieres determinar la versión de python, te recomiendo:

 PY2 = sys.version_info.major == 2 PY3 = sys.version_info.major == 3 # or import six # Python 2 / 3 compatability module six.PY2 # is this Python 2 six.PY3 # is this Python 3 

Decisiones de Python basadas en la versión.

No olvide que las primeras versiones de Python 2 variarán de 2.7. Me gusta planear todas las contingencias, por lo que el siguiente código es excepcional (literalmente) si se usa una versión de Python anterior a 2.7.

 # If you want to use and if/then/else block... import sys major = sys.version_info.major minor = sys.version_info.minor if major == 3: # Python 3 exception handling print("Do something with Python {}.{} code.".format(major, minor)) elif major == 2: # Python 2 exception handling if minor >= 7: # Python 2.7 print("Do something with Python {}.{} code.".format(major, minor)) else: # Python 2.6 and earlier exception handling assert minor >= 2, "Please use Python 2.7 or later, not {}.{}.".format(major,minor) else: assert major >= 2, "Sorry, I'm not writing code for pre-version 2 Python. It just ain't happening. You are using Python {}.{}.".format(major,minor) assert major > 3, "I can't handle Python versions that haven't been written yet.. You are using Python {}.{}.".format(major,minor) 

Manejo de excepciones en Python 2 y 3

python-future es la capa de compatibilidad que falta entre Python 2 y Python 3. Le permite usar un solo código limpio compatible con Python 3.x para admitir Python 2 y Python 3 con una sobrecarga mínima.

Proporciona paquetes futuros y pasados ​​con backports y puertos de funciones de Python 3 y 2. También viene con futurizar y pasteurizar, scripts personalizados basados ​​en 2to3 que le ayudan a convertir código Py2 o Py3 fácilmente para admitir Python 2 y 3 en una base de código Py3-style limpia, módulo por módulo. http://python-future.org/overview.html

Consulte la documentación del futuro módulo de python en http://python-future.org/ . A continuación, se encuentra una copia de las partes de la página.

Aumentar excepciones

 import future # pip install future import builtins # pip install future import past # pip install future import six # pip install six 

Sólo Python 2:

 raise ValueError, "dodgy value" 

Python 2 y 3:

 raise ValueError("dodgy value") Raising exceptions with a traceback: 

Sólo Python 2:

 traceback = sys.exc_info()[2] raise ValueError, "dodgy value", traceback 

Sólo Python 3:

 raise ValueError("dodgy value").with_traceback() 

Python 2 y 3: opción 1

 from six import reraise as raise_ # or from future.utils import raise_ traceback = sys.exc_info()[2] raise_(ValueError, "dodgy value", traceback) 

Python 2 y 3: opción 2

 from future.utils import raise_with_traceback raise_with_traceback(ValueError("dodgy value")) Exception chaining (PEP 3134): 

Preparar:

 class DatabaseError(Exception): pass 

Sólo Python 3

 class FileDatabase: def __init__(self, filename): try: self.file = open(filename) except IOError as exc: raise DatabaseError('failed to open') from exc 

Python 2 y 3:

 from future.utils import raise_from class FileDatabase: def __init__(self, filename): try: self.file = open(filename) except IOError as exc: raise_from(DatabaseError('failed to open'), exc) 

Probando lo anterior:

 try: fd = FileDatabase('non_existent_file.txt') except Exception as e: assert isinstance(e.__cause__, IOError) # FileNotFoundError on Py3.3+ inherits from IOError 

Atrapando excepciones

Sólo Python 2:

 try: ... except ValueError, e: ... 

Python 2 y 3:

 try: ... except ValueError as e: ...