如何编写与Python 2和Python 3兼容的异常重新加载代码?

时间:2013-01-24 14:33:25

标签: python python-3.x python-2.x

我正在尝试使我的WSGI服务器实现与Python 2和Python 3兼容。我有这个代码:

def start_response(status, response_headers, exc_info = None):
    if exc_info:
        try:
            if headers_sent:
                # Re-raise original exception if headers sent.
                raise exc_info[0], exc_info[1], exc_info[2]
        finally:
            # Avoid dangling circular ref.
            exc_info = None
    elif headers_set:
        raise AssertionError("Headers already set!")

    headers_set[:] = [status, response_headers]
    return write

......相关部分是:

# Re-raise original exception if headers sent.
raise exc_info[0], exc_info[1], exc_info[2]

Python 3不再支持该语法,因此必须将其翻译为:

raise exc_info[0].with_traceback(exc_info[1], exc_info[2])

问题:Python 2语法在Python 3中生成解析错误。如何编写可由Python 2和Python 3解析的代码?我尝试了以下方法,但这不起作用:

if sys.version_info[0] >= 3:
    raise exc_info[0].with_traceback(exc_info[1], exc_info[2])
else:
    eval("raise exc_info[0], exc_info[1], exc_info[2]; 1", None, { 'exc_info': exc_info })

2 个答案:

答案 0 :(得分:46)

您可以使用six吗?它的存在是为了解决这个问题。

import six, sys
six.reraise(*sys.exc_info())

请参阅:https://pythonhosted.org/six/index.html#six.reraise

答案 1 :(得分:0)

你可以做一些有创意的事。

检查代码的开头 - 你的构造函数或其他什么,检查你正在使用的python版本,因为你的普通版本检查工具不能正常工作,请尝试这样做:

try:
  eval('a python 3 expression') # something that only works in python3+
  python_version = 3
except:
  python_version = 2

然后,您的其余代码可以轻松地引用它以了解要使用的内容。

至于解析错误,你可以在函数中使用exec,如下所示:

def what_to_run():
    if python_version = 3:
        return 'raise exc_info[0].with_traceback(exc_info[1], exc_info[2])'
    else:
        return 'raise exc_info[0], exc_info[1], exc_info[2]'

在你的功能中你会写这个:

def start_response(status, response_headers, exc_info = None):
    if exc_info:
        try:
            if headers_sent:
                # Re-raise original exception if headers sent.
                exec(what_to_run())
        finally:
            # Avoid dangling circular ref.
            exc_info = None
    elif headers_set:
        raise AssertionError("Headers already set!")

    headers_set[:] = [status, response_headers]
    return write

有点乱,没有经过测试,但它应该工作,至少你理解这个想法。