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 <インスタンス>:
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で議論されている。
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のためだけに色々と対応しなければならない事柄がある。