29.5. 警告—警告制御—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.6/library/warnings
移動先:案内検索

29.5。 警告 —警告制御

ソースコード: :source: `Lib / warnings.py`



警告メッセージは通常、プログラム内のある状態をユーザーに警告するのに役立つ状況で発行されます。この状態では、(通常は)例外を発生させてプログラムを終了する必要はありません。 たとえば、プログラムが廃止されたモジュールを使用しているときに警告を発行したい場合があります。

Pythonプログラマーは、このモジュールで定義されている warn()関数を呼び出すことによって警告を発行します。 (Cプログラマーは PyErr_WarnEx()を使用します。詳細については、例外処理を参照してください)。

警告メッセージは通常sys.stderrに書き込まれますが、すべての警告を無視することから例外に変えることまで、その配置を柔軟に変更できます。 警告の処理は、警告カテゴリ(以下を参照)、警告メッセージのテキスト、および警告が発行されるソースの場所によって異なります。 通常、同じソースの場所に対する特定の警告の繰り返しは抑制されます。

警告制御には2つの段階があります。最初に、警告が発行されるたびに、メッセージを発行する必要があるかどうかが決定されます。 次に、メッセージを発行する場合は、ユーザーが設定可能なフックを使用してフォーマットおよび印刷します。

警告メッセージを発行するかどうかの決定は、一致するルールとアクションのシーケンスである警告フィルターによって制御されます。 filterwarnings()を呼び出すことでルールをフィルターに追加し、 resetwarnings()を呼び出すことでデフォルトの状態にリセットできます。

警告メッセージの出力は、 showwarning()を呼び出すことによって実行されますが、これはオーバーライドされる可能性があります。 この関数のデフォルトの実装は、 formatwarning()を呼び出すことによってメッセージをフォーマットします。これは、カスタム実装でも使用できます。

も参照してください

logging.captureWarnings()を使用すると、標準のロギングインフラストラクチャですべての警告を処理できます。


29.5.1。 警告カテゴリ

警告カテゴリを表す組み込みの例外がいくつかあります。 この分類は、警告のグループを除外できるようにするのに役立ちます。 現在、次の警告カテゴリクラスが定義されています。

クラス 説明
Warning これは、すべての警告カテゴリクラスの基本クラスです。 Exception のサブクラスです。
UserWarning warn()のデフォルトカテゴリ。
DeprecationWarning 非推奨の機能に関する警告の基本カテゴリ(デフォルトでは無視されます)。
SyntaxWarning 疑わしい構文機能に関する警告の基本カテゴリ。
RuntimeWarning 疑わしいランタイム機能に関する警告の基本カテゴリ。
FutureWarning 将来意味的に変更される構成に関する警告の基本カテゴリー。
PendingDeprecationWarning 将来非推奨になる機能に関する警告の基本カテゴリ(デフォルトでは無視されます)。
ImportWarning モジュールのインポートプロセス中にトリガーされる警告の基本カテゴリ(デフォルトでは無視されます)。
UnicodeWarning Unicodeに関連する警告の基本カテゴリ。
BytesWarning bytes および bytearray に関連する警告の基本カテゴリ。
ResourceWarning リソースの使用に関連する警告の基本カテゴリ。

これらは技術的には組み込みの例外ですが、概念的には警告メカニズムに属しているため、ここに記載されています。

ユーザーコードは、標準の警告カテゴリの1つをサブクラス化することにより、追加の警告カテゴリを定義できます。 警告カテゴリは、常に Warning クラスのサブクラスである必要があります。


29.5.2。 警告フィルター

警告フィルターは、警告を無視するか、表示するか、エラーに変えるか(例外を発生させるか)を制御します。

概念的には、警告フィルターはフィルター仕様の順序付きリストを維持します。 特定の警告は、一致するものが見つかるまで、リスト内の各フィルター仕様と順番に照合されます。 試合は試合の性質を決定します。 各エントリは、( actionmessagecategorymodulelineno )の形式のタプルです。どこ:

  • action は、次のいずれかの文字列です。

    価値

    配置

    "error"

    一致する警告を例外に変える

    "ignore"

    一致する警告を出力しない

    "always"

    常に一致する警告を出力します

    "default"

    警告が発行された場所ごとに、一致する警告の最初の発生を印刷します

    "module"

    警告が発行された各モジュールの一致する警告の最初の発生を出力します

    "once"

    場所に関係なく、一致する警告が最初に発生した場合にのみ出力します

  • message は、警告メッセージの先頭が一致する必要がある正規表現を含む文字列です。 式は常に大文字と小文字を区別しないようにコンパイルされます。

  • category はクラス( Warning のサブクラス)であり、一致するには警告カテゴリがサブクラスである必要があります。

  • module は、モジュール名が一致する必要がある正規表現を含む文字列です。 式では、大文字と小文字が区別されるようにコンパイルされています。

  • lineno は、警告が発生した行番号が一致する必要がある整数、または0がすべての行番号と一致する必要がある整数です。

Warning クラスは組み込みの Exception クラスから派生しているため、警告をエラーに変えるには、単にcategory(message)を発生させます。

警告フィルターは、Pythonインタープリターコマンドラインに渡される -W オプションによって初期化されます。 インタプリタは、すべての -W オプションの引数を、sys.warnoptionsに解釈せずに保存します。 警告モジュールは、最初にインポートされたときにこれらを解析します(sys.stderrにメッセージを出力した後、無効なオプションは無視されます)。

29.5.2.1。 デフォルトの警告フィルター

デフォルトでは、Pythonはいくつかの警告フィルターをインストールします。これらは、 -W に渡されたコマンドラインオプションと filterwarnings()の呼び出しによってオーバーライドできます。

バージョン3.2で変更: PendingDeprecationWarning に加えて、 DeprecationWarning がデフォルトで無視されるようになりました。


29.5.3。 警告を一時的に抑制する

非推奨の関数などの警告が発生することがわかっているが、警告を表示したくないコードを使用している場合は、 catch_warnings コンテキストマネージャーを使用して警告を抑制することができます。

import warnings

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

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()

コンテキストマネージャ内では、すべての警告は単に無視されます。 これにより、非推奨のコードの使用を認識していない可能性のある他のコードの警告を抑制せずに、警告を表示せずに既知の非推奨のコードを使用できます。 注:これは、シングルスレッドアプリケーションでのみ保証されます。 2つ以上のスレッドが catch_warnings コンテキストマネージャーを同時に使用する場合、動作は定義されていません。


29.5.4。 警告のテスト

コードによって発生した警告をテストするには、 catch_warnings コンテキストマネージャーを使用します。 これを使用すると、警告フィルターを一時的に変更して、テストを容易にすることができます。 たとえば、次の手順を実行して、発生したすべての警告をキャプチャして確認します。

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)

alwaysの代わりにerrorを使用して、すべての警告を例外にすることもできます。 once / defaultルールが原因ですでに警告が発生している場合は、どのフィルターが設定されていても、警告が表示されない限り、警告は再度表示されないことに注意してください。警告に関連するレジストリがクリアされました。

コンテキストマネージャが終了すると、警告フィルタはコンテキストが入力されたときの状態に復元されます。 これにより、テスト間で予期しない方法でテストが警告フィルターを変更し、テスト結果が不確定になるのを防ぎます。 モジュール内の showwarning()関数も元の値に復元されます。 注:これは、シングルスレッドアプリケーションでのみ保証されます。 2つ以上のスレッドが catch_warnings コンテキストマネージャーを同時に使用する場合、動作は定義されていません。

同じ種類の警告を発する複数の操作をテストする場合、各操作が新しい警告を発していることを確認する方法でそれらをテストすることが重要です(例: 例外として発生する警告を設定し、操作で例外が発生することを確認するか、各操作後に警告リストの長さが増加し続けることを確認するか、新しい操作の前に警告リストから前のエントリを削除します。


29.5.5。 新しいバージョンのPythonのコードを更新する

開発者のみが関心を持つ警告は、デフォルトでは無視されます。 そのため、通常は無視される警告を表示して、コードをテストする必要があります。 これは、 -Wd をインタープリターに渡すことでコマンドラインから実行できます(これは-W defaultの省略形です)。 これにより、デフォルトで無視される警告を含む、すべての警告のデフォルト処理が有効になります。 発生した警告に対して実行されるアクションを変更するには、 -W に渡される引数を変更するだけです。 -W error。 可能なことの詳細については、 -W フラグを参照してください。

プログラムで-Wdと同じことを行うには、次を使用します。

warnings.simplefilter('default')

このコードはできるだけ早く実行してください。 これにより、発生した警告の登録が、将来の警告の処理方法に予期せず影響を与えることを防ぎます。

デフォルトで特定の警告を無視することは、開発者だけが関心を持つ警告がユーザーに表示されないようにするために行われます。 ユーザーがコードを実行するために使用するインタープリターを必ずしも制御できるとは限らないため、リリースサイクルの間に新しいバージョンのPythonがリリースされる可能性があります。 新しいインタプリタリリースは、古いインタプリタにはなかった新しい警告をコードでトリガーする可能性があります。 使用しているモジュールの DeprecationWarning 。 開発者は、コードが非推奨のモジュールを使用していることを通知したいのですが、ユーザーにとって、この情報は本質的にノイズであり、メリットはありません。

unittest モジュールも更新され、テストの実行中に'default'フィルターを使用するようになりました。


29.5.6。 利用可能な機能

warnings.warn(message, category=None, stacklevel=1, source=None)

警告を発行するか、無視するか、例外を発生させます。 category 引数を指定する場合は、警告カテゴリクラスにする必要があります(上記を参照)。 デフォルトは UserWarning です。 または、メッセージ警告インスタンスにすることもできます。その場合、カテゴリは無視され、message.__class__が使用されます。 この場合、メッセージテキストはstr(message)になります。 この関数は、発行された特定の警告が上記の警告フィルターによってエラーに変更された場合に例外を発生させます。 stacklevel 引数は、次のようにPythonで記述されたラッパー関数で使用できます。

def deprecation(message):
    warnings.warn(message, DeprecationWarning, stacklevel=2)

これにより、警告はdeprecation()自体のソースではなく、deprecation()の呼び出し元を参照するようになります(後者は警告メッセージの目的を無効にするため)。

source は、指定されている場合、 ResourceWarning を発行した破棄されたオブジェクトです。

バージョン3.6で変更: source パラメーターが追加されました。

warnings.warn_explicit(message, category, filename, lineno, module=None, registry=None, module_globals=None, source=None)

これは、 warn()の機能への低レベルのインターフェイスであり、メッセージ、カテゴリ、ファイル名、行番号、およびオプションでモジュール名とレジストリ(__warningregistry__モジュールの辞書)。 モジュール名のデフォルトは、.pyが削除されたファイル名です。 レジストリが渡されない場合、警告は抑制されません。 message は文字列である必要があり、 categoryWarning または message のサブクラスは Warning インスタンスである可能性があります。この場合、カテゴリは無視されます。

module_globals が指定されている場合は、警告が発行されるコードで使用されているグローバル名前空間である必要があります。 (この引数は、zipファイルまたはその他のファイルシステム以外のインポートソースにあるモジュールのソースの表示をサポートするために使用されます)。

source は、指定されている場合、 ResourceWarning を発行した破棄されたオブジェクトです。

バージョン3.6で変更: source パラメーターを追加します。

warnings.showwarning(message, category, filename, lineno, file=None, line=None)
ファイルに警告を書き込みます。 デフォルトの実装はformatwarning(message, category, filename, lineno, line)を呼び出し、結果の文字列をファイルに書き込みます。デフォルトはsys.stderrです。 warnings.showwarningに割り当てることで、この関数を呼び出し可能な関数に置き換えることができます。 line は、警告メッセージに含まれるソースコードの行です。 line が指定されていない場合、 showwarning()filename および lineno で指定された行を読み取ろうとします。
warnings.formatwarning(message, category, filename, lineno, line=None)
警告を標準的な方法でフォーマットします。 これは、埋め込まれた改行を含み、改行で終わる文字列を返します。 line は、警告メッセージに含まれるソースコードの行です。 line が指定されていない場合、 formatwarning()filename および lineno で指定された行を読み取ろうとします。
warnings.filterwarnings(action, message=, category=Warning, module=, lineno=0, append=False)
警告フィルター仕様のリストにエントリを挿入します。 エントリはデフォルトで先頭に挿入されます。 append がtrueの場合、最後に挿入されます。 これにより、引数のタイプがチェックされ、メッセージおよびモジュールの正規表現がコンパイルされ、警告フィルターのリストにタプルとして挿入されます。 両方が特定の警告に一致する場合、リストの先頭に近いエントリは、リストの後半のエントリを上書きします。 省略された引数は、デフォルトですべてに一致する値になります。
warnings.simplefilter(action, category=Warning, lineno=0, append=False)
警告フィルター仕様のリストに簡単なエントリを挿入します。 関数パラメーターの意味は filterwarnings()と同じですが、挿入されたフィルターは、カテゴリーと行番号が一致する限り、どのモジュールのどのメッセージとも常に一致するため、正規表現は必要ありません。
warnings.resetwarnings()
警告フィルターをリセットします。 これにより、 -W コマンドラインオプションや simplefilter()の呼び出しを含む、 filterwarnings()への以前のすべての呼び出しの効果が破棄されます。


29.5.7。 利用可能なコンテキストマネージャー

class warnings.catch_warnings(\*, record=False, module=None)

警告フィルターと showwarning()関数をコピーし、終了時に復元するコンテキストマネージャー。 record 引数が False (デフォルト)の場合、コンテキストマネージャーはエントリ時に None を返します。 recordTrue の場合、カスタム showwarning()関数(sys.stdout)。 リスト内の各オブジェクトには、 showwarning()の引数と同じ名前の属性があります。

module 引数は、フィルターが保護される warnings をインポートしたときに返されるモジュールの代わりに使用されるモジュールを取ります。 この引数は、主に警告モジュール自体をテストするために存在します。

ノート

catch_warnings マネージャーは、モジュールの showwarning()関数とフィルター仕様の内部リストを置き換え、後で復元することで機能します。 これは、コンテキストマネージャーがグローバル状態を変更しているため、スレッドセーフではないことを意味します。