Pythonでは、警告が例外であるかのようにどのようにして警告をキャッチしますか?


103

私のpythonコードで使用するサードパーティライブラリ(Cで記述)が警告を発行しています。try except構文を使用してこれらの警告を適切に処理できるようにしたいと考えています。これを行う方法はありますか?


2
それらの警告は、書かれたテキストメッセージだけが標準エラーですか?
Fenikso

1
フェニクソ:はっきりとはわかりませんが、本当の警告のようです
ボリス

1
「実際の警告」をどのように認識しますか?Cではコンパイル中に実際に警告が出ると思いました。
Fenikso

warnings.filterwarningsまさにあなたが望むことをしますが、私はあなたの問題が何であるか理解できませんか?
Rosh Oxymoron、2011

4
@ Fenikso、@ Rosh Oxymoron、あなたは正しかった。私の間違い。warnings.filterwarnigns('error')仕事をします。このソリューションを提案した元の回答が見つかりません
ボリスゴレリック

回答:


51

pythonハンドブックから引用するには(27.6.4。テスト警告):

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings(record=True) as w:
    # Cause all warnings to always be triggered.
    warnings.simplefilter("always")
    # Trigger a warning.
    fxn()
    # Verify some things
    assert len(w) == 1
    assert issubclass(w[-1].category, DeprecationWarning)
    assert "deprecated" in str(w[-1].message)

6
これが答えですtry except。構文の使い方を教えてくれます。
Unapiedra 2014年

これには、niekasの答えよりも優れている点がありfnxます。何かを返す場合、その結果を保持します(警告を管理できます)。
Pietro Battiston

これはOPの質問には答えません。これは、wanringの処理ではなく、テストではありませんでした。ただし、以下のniekasの回答は、警告の処理方法を示しています。
Biggsy

上記の関数は、関数が警告を断続的に返すだけの場合は機能fxn()しないことに注意しwてください。警告を返さないイベントでは、空のリストになります。場合はw空のリスト(すなわちである[])、そしてコードを実行すると、あなたに次のエラーを与えます:IndexError: list index out of range。:あなただけのキャプチャ警告のフォーマットやチェックプロパティに探しているなら、それは、forループを使用する方が良いでしょうfor x in w: print(f'{x.category.__name__}: {str(x.message)}')
スティーブンM.モーティマー

130

警告をエラーとして処理するには、これを使用するだけです。

import warnings
warnings.filterwarnings("error")

この後、エラーと同じ警告をキャッチできるようになります。たとえば、次のように機能します。

try:
    some_heavy_calculations()
except RuntimeWarning:
    import ipdb; ipdb.set_trace()

PS追加この回答のコメントで最高の答えが誤った綴り含まれているので:filterwarnigns代わりにfilterwarnings


8
スタックトレースだけを見たい場合は、最初の2行で十分です。
z0r 2017

5
これは完璧です。警告が発行されたらすぐにスクリプトの実行を停止して、関連するデバッグ情報を出力して問題を修正したかっただけです。
Praveen

1
filterwarningsをキャッチするために呼び出しを行う必要はありませんWarnings。少なくともpython 3では機能します。
naught101

1
受け入れられた回答は、OPの質問には回答しません。この答えはそうです。これは、検索でこの質問が見つかったときに探していた答えです。
Biggsy


15

これは、カスタム警告のみを処理する方法をより明確にするバリエーションです。

import warnings
with warnings.catch_warnings(record=True) as w:
    # Cause all warnings to always be triggered.
    warnings.simplefilter("always")

    # Call some code that triggers a custom warning.
    functionThatRaisesWarning()

    # ignore any non-custom warnings that may be in the list
    w = filter(lambda i: issubclass(i.category, UserWarning), w)

    if len(w):
        # do something with the first warning
        email_admins(w[0].message)

4

場合によっては、警告をエラーに変換するためにctypesを使用する必要があります。例えば:

str(b'test')  # no error
import warnings
warnings.simplefilter('error', BytesWarning)
str(b'test')  # still no error
import ctypes
ctypes.c_int.in_dll(ctypes.pythonapi, 'Py_BytesWarningFlag').value = 2
str(b'test')  # this raises an error

この回答は、特定の警告タイプでのみエラーが発生する方法を示すために単純に構成されています。ほとんどすべての大規模なソフトウェアプロジェクトでwarnings.simplefilter('error')は、ログに表示された警告のトレースバックを取得できませんが、代わりに、以前にフィルター処理された警告からトレースバックを取得します。simplefilterCLIを呼び出している場合は、使用することも最も簡単な方法です。
AlanSE
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.