web-dev-qa-db-ja.com

Pythonで例外メッセージを適切に取得する方法

Pythonの標準ライブラリのコンポーネントから例外のメッセージを取得する最良の方法は何ですか?

場合によっては、次のようにmessageフィールドから取得できることに気付きました。

try:
  pass
except Exception as ex:
  print(ex.message)

ただし、場合によっては(たとえば、ソケットエラーの場合)、次のようにする必要があります。

try:
  pass
except socket.error as ex:
  print(ex)

これらの状況のほとんどをカバーする標準的な方法はあるのだろうか?

61
FrozenHeart

組み込みエラーのドキュメント を見ると、ほとんどのExceptionクラスが最初の引数をmessage属性として割り当てていることがわかります。しかし、すべてがそうするわけではありません。

特に、EnvironmentError(サブクラスIOErrorおよびOSError)には、errnoの2番目の引数、strerrorの2番目の引数があります。 messageはありません... strerrorは、通常messageになるものとほぼ同じです。

より一般的には、Exceptionのサブクラスは何でもできます。 message属性を持つ場合と持たない場合があります。将来の組み込みExceptionsにはmessage属性が含まれない可能性があります。サードパーティのライブラリまたはユーザーコードからインポートされたExceptionサブクラスには、message属性がない場合があります。

これを処理する適切な方法は、キャッチする特定のExceptionサブクラスを特定し、except Exceptionですべての代わりにサブクラスのみをキャッチし、特定のサブクラスが定義する属性を利用することだと思います欲しいです。

print何かをしなければならない場合、Exception属性を持っているかどうかに関係なく、キャッチされたmessage自体を印刷することが、おそらくあなたが望むことをする可能性が高いと思います。

次のように、必要に応じてメッセージ属性を確認することもできますが、面倒だと思われるため、実際には提案しません。

try:
    pass
except Exception as e:
    # Just print(e) is cleaner and more likely what you want,
    # but if you insist on printing message specifically whenever possible...
    if hasattr(e, 'message'):
        print(e.message)
    else:
        print(e)
54
ArtOfWarfare

@ artofwarfare によって提供される答えを改善するために、ここにmessage属性をチェックしてそれを印刷するか、フォールバックとしてExceptionオブジェクトを印刷するより適切な方法を検討します。

try:
    pass 
except Exception as e:
    print getattr(e, 'message', repr(e))

reprへの呼び出しはオプションですが、使用例によっては必要な場合があります。


#1:を更新:

@ MadPhysicist によるコメントに続いて、ここにreprの呼び出しが必要な理由の証拠があります。インタープリターで次のコードを実行してみてください。

try:
    raise Exception 
except Exception as e:
    print(getattr(e, 'message', repr(e)))
    print(getattr(e, 'message', str(e)))

更新#2:

Python 2.7および3.5の詳細を含むデモを次に示します。 https://Gist.github.com/takwas/3b7a6edddef783f2abddffda1439f5

16
acetakwas

同じ問題がありました。最善の解決策はlog.exceptionを使用することだと思います。これにより、次のようなスタックトレースとエラーメッセージが自動的に出力されます。

try:
    pass
    log.info('Success')
except:
    log.exception('Failed')
0
Bill Z