24

WSGIサーバーの実装をPython2とPython3の両方と互換性を持たせようとしています。次のコードがあります。

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

問題:Python2構文はPython3で解析エラーを生成します。Python2とPython3の両方で解析できるコードを作成するにはどうすればよいですか?私は以下を試しましたが、それはうまくいきません:

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 })
4

2 に答える 2

50

使えますsixか?この問題を解決するために存在します。

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

参照:https ://six.readthedocs.io/index.html#six.reraise

于 2013-01-24T15:38:26.990 に答える
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

少し厄介で、テストされていませんが、少なくともあなたはその考えを理解しているので、うまくいくはずです。

于 2013-01-24T14:42:39.927 に答える