1. ホーム
  2. python

[解決済み] メソッドを呼び出すとどのような例外が投げられるかを知るにはどうすればよいですか?

2023-01-30 03:59:10

質問

Pythonのコードを実行するときに、どのような例外が発生するかを(コーディング時に)知る方法はありますか?

私はどの例外型が投げられるか分からないので、90%の時間は基本Exceptionクラスをキャッチすることになります(何度も例外が深いところから伝播されることがあるので、ドキュメントを読むことは常に役に立ちません。そして、多くの場合、ドキュメントは更新されていないか、正しいものではありません)。

これをチェックするための何らかのツールはありますか(Pythonコードとライブラリを読むことによってなど)?

どのように解決するのですか?

静的な型付けルールがないため、解決策は不正確なものしかないでしょう。

例外をチェックするようなツールは知りませんが、ニーズに合わせて自分でツールを作ってみてはいかがでしょうか(静的解析で少し遊ぶには良い機会です)。

最初の試みとして、ASTを構築する関数を書いて、すべての Raise ノードを見つけ、例外を発生させる一般的なパターン (例: コンストラクタを直接呼び出す) を見つけ出そうとする関数を書くことができます。

では x は次のプログラムであるとする。

x = '''\
if f(x):
    raise IOError(errno.ENOENT, 'not found')
else:
    e = g(x)
    raise e
'''

ASTを構築するには compiler パッケージを使ってASTを構築します。

tree = compiler.parse(x)

次に Raise ビジタークラスを定義します。

class RaiseVisitor(object):
    def __init__(self):
        self.nodes = []
    def visitRaise(self, n):
        self.nodes.append(n)

そして、ASTを集めて歩く Raise ノードを収集します。

v = RaiseVisitor()
compiler.walk(tree, v)

>>> print v.nodes
[
    Raise(
        CallFunc(
            Name('IOError'),
            [Getattr(Name('errno'), 'ENOENT'), Const('not found')],
            None, None),
        None, None),
    Raise(Name('e'), None, None),
]

コンパイラのシンボルテーブルを使ってシンボルを解決したり、データの依存関係を分析したりすることで、続けることができます。あるいは、ただ推論することもできます。 CallFunc(Name('IOError'), ...) というのは間違いなく IOError を意味するはずですが、これは迅速な実用的な結果を得るためにはかなりOKです :)