Python 2.x 和 3.x 中用于引发异常的有效语法?
Valid syntax in both Python 2.x and 3.x for raising exception?
我如何将此代码移植到 Python 3,以便它在 Python 2 和 Python3 中都 运行?
raise BarException, BarException(e), sys.exc_info()[2]
(从http://blog.ionelmc.ro/2014/08/03/the-most-underrated-feature-in-python-3/复制)
加分题
做像
这样的事情有意义吗
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")
您将不得不使用 exec()
因为您不能在 Python 3 中使用 3 参数语法;它会引发语法错误。
一如既往,six
library 已经为您介绍,移植到不依赖于其他 six
定义,它们的版本如下所示:
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")
现在您可以使用:
reraise(BarException, BarException(e), sys.exc_info()[2])
无需进一步测试 Python 版本。
Python 2 / 3 兼容代码引发异常
Six provides simple utilities for wrapping over differences between
Python 2 and Python 3. It is intended to support codebases that work
on both Python 2 and 3 without modification. six consists of only one
Python file, so it is painless to copy into a 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)
从 Python 2 到 Python 3 的转换。
您可以使用 2to3 制作代码的 Python 3 副本。
2to3 is a Python program that reads Python 2.x source code and applies
a series of fixers to transform it into valid Python 3.x code. The
standard library contains a rich set of fixers that will handle almost
all code. 2to3 supporting library lib2to3 is, however, a flexible and
generic library, so it is possible to write your own fixers for 2to3.
lib2to3 could also be adapted to custom applications in which Python
code needs to be edited automatically.
...
2to3 can also write the needed modifications right back to the source
file. (Of course, a backup of the original is also be made unless -n
is also given.) Writing the changes back is enabled with the -w flag:
$ 2to3 -w example.py
Python版本确定
如果要确定python版本,我推荐:
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
Python 基于版本的决定
不要忘记 Python 2 的早期版本与 2.7 不同。我喜欢为所有突发事件做好计划,因此如果使用 2.7 之前的 Python 版本,则以下代码将例外(litteraly)。
# 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)
Python 2 和 3
中的异常处理
python-future is the missing compatibility layer between Python 2 and
Python 3. It allows you to use a single, clean 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
of features from Python 3 and 2. It also comes with futurize and
pasteurize, customized 2to3-based scripts that helps you to convert
either Py2 or Py3 code easily to support both Python 2 and 3 in a
single clean Py3-style codebase, module by module.
http://python-future.org/overview.html
在 http://python-future.org/ 上查看 python 的未来模块文档。
下面是该页面的引发异常和捕获异常部分的副本。
Raising Exceptions
import future # pip install future
import builtins # pip install future
import past # pip install future
import six # pip install six
Python 仅 2 个:
raise ValueError, "dodgy value"
Python 2 和 3:
raise ValueError("dodgy value")
Raising exceptions with a traceback:
Python 仅 2 个:
traceback = sys.exc_info()[2]
raise ValueError, "dodgy value", traceback
Python 3只:
raise ValueError("dodgy value").with_traceback()
Python2和3:选项1
from six import reraise as raise_
# or
from future.utils import raise_
traceback = sys.exc_info()[2]
raise_(ValueError, "dodgy value", traceback)
Python2和3:选项2
from future.utils import raise_with_traceback
raise_with_traceback(ValueError("dodgy value"))
Exception chaining (PEP 3134):
设置:
class DatabaseError(Exception):
pass
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 和 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)
测试以上内容:
try:
fd = FileDatabase('non_existent_file.txt')
except Exception as e:
assert isinstance(e.__cause__, IOError) # FileNotFoundError on Py3.3+ inherits from IOError
Catching exceptions
Python 仅 2 个:
try:
...
except ValueError, e:
...
Python 2 和 3:
try:
...
except ValueError as e:
...
我如何将此代码移植到 Python 3,以便它在 Python 2 和 Python3 中都 运行?
raise BarException, BarException(e), sys.exc_info()[2]
(从http://blog.ionelmc.ro/2014/08/03/the-most-underrated-feature-in-python-3/复制)
加分题
做像
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")
您将不得不使用 exec()
因为您不能在 Python 3 中使用 3 参数语法;它会引发语法错误。
一如既往,six
library 已经为您介绍,移植到不依赖于其他 six
定义,它们的版本如下所示:
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")
现在您可以使用:
reraise(BarException, BarException(e), sys.exc_info()[2])
无需进一步测试 Python 版本。
Python 2 / 3 兼容代码引发异常
Six provides simple utilities for wrapping over differences between Python 2 and Python 3. It is intended to support codebases that work on both Python 2 and 3 without modification. six consists of only one Python file, so it is painless to copy into a 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)
从 Python 2 到 Python 3 的转换。
您可以使用 2to3 制作代码的 Python 3 副本。
2to3 is a Python program that reads Python 2.x source code and applies a series of fixers to transform it into valid Python 3.x code. The standard library contains a rich set of fixers that will handle almost all code. 2to3 supporting library lib2to3 is, however, a flexible and generic library, so it is possible to write your own fixers for 2to3. lib2to3 could also be adapted to custom applications in which Python code needs to be edited automatically.
...
2to3 can also write the needed modifications right back to the source file. (Of course, a backup of the original is also be made unless -n is also given.) Writing the changes back is enabled with the -w flag:
$ 2to3 -w example.py
Python版本确定
如果要确定python版本,我推荐:
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
Python 基于版本的决定
不要忘记 Python 2 的早期版本与 2.7 不同。我喜欢为所有突发事件做好计划,因此如果使用 2.7 之前的 Python 版本,则以下代码将例外(litteraly)。
# 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)
Python 2 和 3
中的异常处理python-future is the missing compatibility layer between Python 2 and Python 3. It allows you to use a single, clean 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 of features from Python 3 and 2. It also comes with futurize and pasteurize, customized 2to3-based scripts that helps you to convert either Py2 or Py3 code easily to support both Python 2 and 3 in a single clean Py3-style codebase, module by module. http://python-future.org/overview.html
在 http://python-future.org/ 上查看 python 的未来模块文档。 下面是该页面的引发异常和捕获异常部分的副本。
Raising Exceptions
import future # pip install future
import builtins # pip install future
import past # pip install future
import six # pip install six
Python 仅 2 个:
raise ValueError, "dodgy value"
Python 2 和 3:
raise ValueError("dodgy value")
Raising exceptions with a traceback:
Python 仅 2 个:
traceback = sys.exc_info()[2]
raise ValueError, "dodgy value", traceback
Python 3只:
raise ValueError("dodgy value").with_traceback()
Python2和3:选项1
from six import reraise as raise_
# or
from future.utils import raise_
traceback = sys.exc_info()[2]
raise_(ValueError, "dodgy value", traceback)
Python2和3:选项2
from future.utils import raise_with_traceback
raise_with_traceback(ValueError("dodgy value"))
Exception chaining (PEP 3134):
设置:
class DatabaseError(Exception):
pass
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 和 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)
测试以上内容:
try:
fd = FileDatabase('non_existent_file.txt')
except Exception as e:
assert isinstance(e.__cause__, IOError) # FileNotFoundError on Py3.3+ inherits from IOError
Catching exceptions
Python 仅 2 个:
try:
...
except ValueError, e:
...
Python 2 和 3:
try:
...
except ValueError as e:
...