Python
python3

エラーの情報を取得するmessageとwith_traceback

Python 3.6.3 でエラーの情報を取得する際に.messageが使えなかった。

2015年にQiitaにまとめられた記事でpythonの勉強をしていて、エラーの情報を取得する回に

[example.py]
try:
    a = 10 / 0
    print("{0}".format(a))
except ZeroDivisionError as e:
    print("message:{0}".format(e.message))

と処理する際に

Traceback (most recent call last):
  File "py3.division_by_zero_info.py", line 9, in <module>
    print("message:{0}".format(e.message))
AttributeError: 'ZeroDivisionError' object has no attribute 'message'

とAttributeErrorが出てうまく取得できなかった。

dir()でエラーの持つアトリビュートが調べられる

色々調べまわっていると、dir()でオブジェクトの持つアトリビュートの一覧を確認できることを発見して早速試すと、

[dir.py]
try:
  a = 10 / 0
  print("{0}".format(a))
except Exception as e:
  print(dir(e))

以下、結果

['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', 
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', 
'__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', 
'args', 'with_traceback']

バーっと出てきた。argsは問題なさそう。messageは見当たらない。

気になるのでバージョンを下げて(2.7.14)、もう一度dir()を試す。

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',
 '__getitem__', '__getslice__', '__hash__', '__init__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__',
'__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', 
'args', 'message']

message 発見ーーーー。

messageで出力する

2.7.14のままmessageで出力してみる。

[message.py]
try:
  a = 10 / 0
  print("{0}".format(a))
except Exception as e:
  print("message:{0}".format(e.message))

以下、結果

message:integer division or modulo by zero

ちゃんと取得できた!

with_tracebackで出力する

3.6.3に戻してwith_tracebackで出力する。
with_tracebackを使う場合はsysをimportしてスタックトレース(処理を順番に格納すること?)の情報をexec_info()で取得した上で行う。

[with_traceback.py]
import sys
try:
  a = 10 / 0
  print("{0}".format(a))
except Exception as e:
  tb = sys.exc_info()[2]
  print("message:{0}".format(e.with_traceback(tb)))

以下、結果

message:division by zero

無事に出力できた。
情報の内容も少し異なっているし、基底になっているクラスの違いもあるようで(内容が異なっているのかはわかってない)、そういうのも関係しているんでしょうか・・・

お世話になりました。

Python基礎講座(11 例外) - Qiita
Pythonの組み込み例外の木構造を見てみる - Qiita
オブジェクトのアトリビュートの一覧を取得す
5. 組み込み例外 — Python 3.6.3 ドキュメント
29.1. sys — システムパラメータと関数 — Python 3.6.3 ドキュメント