Python 2 / 3 兼容代码引发异常
Six 提供了简单的实用程序来解决两者之间的差异
Python 2 和 Python 3。它旨在支持有效的代码库
在 Python 2 和 3 上都没有修改。六个只包含一个
Python 文件,因此可以轻松复制到项目中。
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 是一个 Python 程序,它读取 Python 2.x 源代码并应用
一系列修复程序将其转换为有效的 Python 3.x 代码。这
标准库包含一组丰富的修复程序,几乎可以处理
所有代码。然而,支持 2to3 的库 lib2to3 是一个灵活且
通用库,因此可以为 2to3 编写自己的修复程序。
lib2to3 也可以适应 Python 的自定义应用程序
代码需要自动编辑。
...
2to3 还可以将所需的修改直接写回源代码
文件。 (当然也可以备份原版,除非-n
也给出了。)使用 -w 标志启用写回更改:
$ 2to3 -w example.py
(来自https://docs.python.org/3.0/library/2to3.html)
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 版本,以下代码将出现异常(字面意思)。
# 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 是 Python 2 和
Python 3。它允许您使用单一、干净的 Python 3.x 兼容
代码库以最小的开销同时支持 Python 2 和 Python 3。
它为未来和过去的包提供反向端口和正向端口
Python 3 和 2 的功能。它还带有 futurize 和
巴氏杀菌,定制的基于 2to3 的脚本,可帮助您转换
Py2 或 Py3 代码轻松支持 Python 2 和 3
单个干净的 Py3 风格的代码库,一个模块一个模块。
http://python-future.org/overview.html
请参阅http://python-future.org/ 上的 python 未来模块文档。
以下是该页面的“引发异常和排除异常”部分的副本。
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()
Python 2 和 3:选项 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 和 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
仅限 Python 2:
try:
...
except ValueError, e:
...
Python 2 和 3:
try:
...
except ValueError as e:
...