Python2.5とPython3で互換性を保つための例外処理の書き方

概要

Python 2.5以下とPython3系で互換性を保つための例外処理の書き方について記載する。 Pythonでは、対応する例外処理の記法がPython 2.5以下、Python 2.6以上、Python3系で異なる。

Pythonバージョンによる例外処理記法の差異

try-except節でexceptの書き方が異なる。 以下に例と共に示す。

Python 2.5以下

Python 2.5では例外処理は以下のように記述する。

try:
    <処理>
except <例外クラス>, <インスタンス>:
    <例外処理>

ここで、exceptの行、<例外クラス><インスタンス>の間がカンマ ,である必要がある。

except <例外クラス>, <インスタンス>:

記述例

try:
    n = 10 * (1 / 0)
except ZeroDivisionError, e:
    print e

Python 3系

Python 3系ではasキーワードが必須となる。

try:
    <処理>
except <例外クラス> as <インスタンス>:
    <例外処理>

ここで、exceptの行、<例外クラス><インスタンス>の間がasである必要がある。

except <例外クラス> as <インスタンス>:

sebastianraschka.com

Handling exceptions

Also the handling of exceptions has slightly changed in Python 3. In Python 3 we have to use the "as" keyword now

記述例

try:
    n = 10 * (1 / 0)
except ZeroDivisionError as e:
    print e

Python 2.6以上(Python 2系)

Python 2.5以下/3系のどちらの記載もできる。

課題

前述の記法ではPython 2.5以下とPython 3系で互換性が無い。 そのため、Python 2.5とPython 3系の両方で動作するexcept区が書けない。

Six: Python 2 and 3 Compatibility Library — six 1.10.0 documentationでは、この問題については吸収することもできない。

対策

sys.exc_infoを利用する

以下のように記載する。

try:
    <処理>
except <例外クラス>:
    _, <インスタンス>, _ = sys.exc_info()
    <例外処理>

同じ課題がStack overflowで議論されている。

stackoverflow.com

You can use one code base on Pythons 2.5 through 3.2, but it isn't easy. You can take a look at coverage.py, which runs on 2.3 through 3.3 with a single code base.

The way to catch an exception and get a reference to the exception that works in all of them is this:

```python except ValueError: _, err, _ = sys.exc_info() #.. use err... This is equivalent to:

except ValueError as err: #.. use err... ```

sys.exc_infoの詳細については公式ドキュメントを参照。

28.1. sys — System-specific parameters and functions — Python 2.7.11 documentation

If no exception is being handled anywhere on the stack, a tuple containing three None values is returned. Otherwise, the values returned are (type, value, traceback). Their meaning is: type gets the exception type of the exception being handled (a class object); value gets the exception parameter (its associated value or the second argument to raise, which is always a class instance if the exception type is a class object); traceback gets a traceback object (see the Reference Manual) which encapsulates the call stack at the point where the exception originally occurred.

Python 2.6以上を使用する

Python 2.5を切り捨てられる環境ではこうするのが一番簡単かつ、綺麗な形になる。 この問題以外にもPython 2.5では対応していないライブラリや記法があり、 Python 2.5のためだけに色々と対応しなければならない事柄がある。

qiita.com