Valid syntax in Python 2.x and 3.x to raise an exception?

How can I port this code to Python 3 so that it runs in both Python 2 and Python3?

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

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

Bonus Question
Does it make sense to do something like

 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") 
0
source share
2 answers

You have to use exec() because you cannot use the syntax of 3 arguments in Python 3; this will result in a syntax error.

As always, six library is already covered, ported so as not to depend on other six definitions, their version is as follows:

 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") 

Now you can use:

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

without further testing for the Python version.

+2
source

Python 2/3 compatible code to create an exception

Six provides simple utilities for transferring the differences between Python 2 and Python 3. It is designed to support codebases that run on both Python 2 and 3 unchanged. six consists of only one python, so copy painlessly to the project. 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) 

Convert from Python 2 to Python 3.

You can make a copy of Python 3 code using 2to3.

2to3 is a Python program that reads the source code of Python 2.x and uses a series of fixers to convert it to actual Python 3.x code. the standard library contains a rich set of latches that will process almost all the code. 2to3, which supports the lib2to3 library, however, is also a flexible and shared library, so you can write your own latches for 2to3. lib2to3 can also be adapted to user applications in which Python code needs to be edited automatically.

...

2to3 can also write the necessary changes directly to the source file. (Of course, a backup copy of the original will also be made, if only -n is also given.) Recording changes back is enabled using the -w flag:

 $ 2to3 -w example.py 

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

Python Version Definition

If you want to determine the version of python, I recommend:

 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 

Version Based Python Solutions

Remember that earlier versions of Python 2 will be different from 2.7. I like to plan all unforeseen situations, so the following code will throw an exception (litteraly) if you are using a version of Python prior to version 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) 

Exception handling in Python 2 and 3

python-future is the missing level of compatibility between Python 2 and Python 3. It allows you to use one pure Python 3.x-compatible codebase to support both Python 2 and Python 3 with minimal overhead.

It provides future and past packages with backports and forward ports functions from Python 3 and 2. It also comes with futurization and pasteurization, customization of 2to3-based scripts that will help you convert either Py2 or Py3 code to easily support both Python 2 and and 3 in a one-time pure code base of type Py3, module modulo. http://python-future.org/overview.html

See the documentation for the upcoming python module at http://python-future.org/ . The following is a copy of the “Exceptions and Corrections Fixes” sections on the page.

Raising exceptions

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

Python 2 only:

 raise ValueError, "dodgy value" 

Python 2 and 3:

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

Python 2 only:

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

Python 3 only:

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

Python 2 and 3: option 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 and 3: option 2

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

Setup:

 class DatabaseError(Exception): pass 

Python 3 only

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

Python 2 and 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) 

Testing above:

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

Catch exceptions

Python 2 only:

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

Python 2 and 3:

 try: ... except ValueError as e: ... 
0
source

Source: https://habr.com/ru/post/1240328/


All Articles