バージョン 2.1 で追加.
警告メッセージは一般に、ユーザに警告しておいた方がよいような状況下にプログラムが置かれているが、その状況は (通常は) 例外を送出したり そのプログラムを終了させるほどの正当な理由がないといった状況で発されます。例えば、プログラムが古いモジュールを使っている場合 には警告を発したくなるかもしれません。
Python プログラマは、このモジュールの warn() 関数を使うことで警告を発することができます。(C 言語のプログラマは PyErr_WarnEx() を使います; 詳細は 例外処理 を参照してください)。
警告メッセージは通常 sys.stderr に出力されますが、その処理方法は、全ての警告に対する無視する処理から警告を例外に変更する 処理まで、柔軟に変更することができます。警告の処理方法は警告カテゴリ (以下参照)、警告メッセージテキスト、そして警告を 発したソースコード上の場所に基づいて変更することができます。ソースコード上の同じ場所に対して特定の警告が繰り返された場合、通常は抑制されます。
警告制御には 2 つの段階 (stage) があります: 第一に、警告が発されるたびに、メッセージを出力すべきかどうか決定が行われます; 次に、 メッセージを出力するなら、メッセージはユーザによって設定が可能なフックを使って書式化され印字されます。
警告メッセージを出力するかどうかの決定は、警告フィルタによって制御されます。警告フィルタは一致規則 (matching rule)と動作からなるシーケンスです。 filterwarnings() を呼び出して一致規則をフィルタに追加する ことができ、 resetwarnings() を呼び出してフィルタを標準設定の状態にリセットすることができます。
警告メッセージの印字は showwarning() を呼び出して行うことができ、この関数は上書きすることができます; この関数の標準の実装では、 formatwarning() を呼び出して警告メッセージを書式化しますが、この関数についても自作の実装を使うことができます。
警告カテゴリを表現する組み込み例外は数多くあります。このカテゴリ化は警告をグループごとフィルタする上で便利です。現在以下の警告カテゴリ クラスが定義されています:
クラス | 記述 |
---|---|
Warning | 全ての警告カテゴリクラスの基底クラスです。 Exception のサブクラスです。 |
UserWarning | warn() の標準のカテゴリです。 |
DeprecationWarning | その機能が廃用化されていることを示す警告カテゴリの基底クラスです。 |
SyntaxWarning | その文法機能があいまいであることを示す警告カテゴリの基底クラスです。 |
RuntimeWarning | その実行時システム機能があいまいであることを示す警告カテゴリの基底クラスです。 |
FutureWarning | その構文の意味付けが将来変更される予定であることを示す警告カテゴリの基底クラスです。 |
PendingDeprecationWarning | 将来その機能が廃用化されることを示す 警告カテゴリの基底クラスです(デフォルトでは無視されます)。 |
ImportWarning | モジュールのインポート処理中に引き起こされる 警告カテゴリの基底クラスです(デフォルトでは無視されます)。 |
UnicodeWarning | Unicode に関係した警告カテゴリの基底クラスです。 |
これらは技術的には組み込み例外ですが、概念的には警告メカニズムに属しているのでここで記述されています。
標準の警告カテゴリをユーザの作成したコード上でサブクラス化することで、さらに別の警告カテゴリを定義することができます。警告カテゴリは常に Warning クラスのサブクラスでなければなりません。
警告フィルタは、ある警告を無視すべきか、表示すべきか、あるいは (例外を送出する) エラーにするべきかを制御します。
概念的には、警告フィルタは複数のフィルタ仕様からなる順番付けられたリストを維持しています; 何らかの特定の警告が生じると、フィルタ仕様の 一致するものが見つかるまで、リスト中の各フィルタとの照合が行われます; 一致したフィルタ仕様がその警告の処理方法を決定します。フィルタの各エントリは (action, message, category, module, lineno) からなるタプルです。ここで:
action は以下の文字列のうちの一つです:
値 |
処理方法 |
---|---|
"error" |
一致した警告を例外に変えます |
"ignore" |
一致した警告を決して出力しません |
"always" |
一致した警告を常に出力します |
"default" |
一致した警告のうち、警告の原因になった ソースコード上の場所ごとに、最初の警告のみ出力します。 |
"module" |
一致した警告のうち、警告の原因になったモジュールごとに、最初の警告のみ出力します。 |
"once" |
一致した警告のうち、警告の原因になった場所にかかわらず最初の警告のみ出力します。 |
message は正規表現を含む文字列で、メッセージはこのパタンに一致しなければなりません (照合時には常に大小文字の区別を しないようにコンパイルされます)。
category はクラス (Warning のサブクラス) です。警告クラスはこのクラスのサブクラスに一致しなければなりません。
module は正規表現を含む文字列で、モジュール名はこのパタンに一致しなければなりません (照合時には常に大小文字の区別を しないようにコンパイルされます)。
lineno 整数で、警告が発生した場所の行番号に一致しなければなりません、すべての行に一致する場合には 0 になります。
Warning クラスは組み込みの Exception クラスから導出されているので、警告をエラーに変えるには単に category(message) を raise します。
警告フィルタは Python インタプリタのコマンドラインに渡される -W オプションで初期化されます。インタプリタは -W オプションに渡される全ての引数を sys.warnoptions ; に変換せずに保存します; warnings モジュールは最初に import された際にこれらの引数を解釈します (無効なオプションは sys.stderr にメッセージを出力した後 無視されます)。
デフォルトでは無視される警告を -Wd をインタプリタに渡すことで有効にすることができます。このオプションは通常はデフォルトで無視さ れるようなものを含む全ての警告のデフォルトでの扱いを有効化します。このような振る舞いは開発中のパッケージをインポートする問題をデバッグする時 にImportWarning を有効化するために使えます。ImportWarning は次のような Python コードを使って明示的に有効化することもできます。
warnings.simplefilter('default', ImportWarning)
廃止予定の関数など、warning を発生させる事を知っているコードを利用する場合に、 warningを表示したくないのであれば、 catch_warnings コンテキストマネージャーを 使ってwarningを抑制することができます。
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
このサンプルのコンテキストマネージャーの中では、全てのwarningが無視されています。 これで、他の廃止予定のコードを含まない(つもりの)部分までwarningを抑止せずに、 廃止予定だと分かっているコードだけwarningを表示させないようにすることができます。
コードがwarningを発生させることをテストするには、 catch_warnings コンテキストマネージャーを利用します。 このくr巣を使うと、一時的にwarningフィルターを操作してテストに利用できます。 例えば、次のコードでは、全ての発生したwarningを取得してチェックしています。
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 isinstance(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
always の代わりに error を利用することで、全てのwarningで例外を発生させることができます。 1つ気をつけないといけないのは、1度 once/default ルールによって発生したwarningは、 フィルターに何をセットしているかにかかわらず、warnings registryをクリアしない限りは 2度と発生しません。
コンテキストマネージャーが終了したら、warningフィルターはコンテキストマネージャーに入る前のものに戻されます。これは、テスト中に予期しない方法でwarningフィルターが変更され、 テスト結果が中途半端になる事を予防します。 このモジュールの showwarning() 関数も元の値に戻されます。
同じ種類のwarningを発生させる複数の操作をテストする場合、 各操作が新しいwarningを発生させている事を確認するのは大切な事です。 (例えば、warningを例外として発生させて各操作が例外を発生させることを確認したり、 warningリストの長さが各操作で増加していることを確認したり、 warningリストを各操作の前に毎回クリアする事ができます。)
警告を発するか、無視するか、あるいは例外を送出します。 category 引数が与えられた場合、警告カテゴリクラスでなければなりません (上を参照してください); 標準の値は UserWarning です。 message を Warning インスタンスで代用する こともできますが、この場合 category は無視され、 message.__class__ が使われ、メッセージ文は str(message) になります。発された例外が前述した警告フィルタによってエラーに変更された場合、この関数は例外を送出します。引数 stacklevel は Python でラッパ関数を書く際に利用することができます。例えば:
def deprecation(message):
warnings.warn(message, DeprecationWarning, stacklevel=2)
こうすることで、警告が参照するソースコード部分を、 deprecation() 自身ではなく deprecation() を 呼び出した側にできます (というのも、前者の場合は警告メッセージの目的を台無しにしてしまうからです)。
warn() の機能に対する低レベルのインタフェースで、メッセージ、警告カテゴリ、ファイル名および行番号、そしてオプションの モジュール名およびレジストリ情報 (モジュールの __warningregistry__ 辞書) を明示的に渡します。モジュール名は標準で .py が取り去られたファイル名になります; レジストリが渡されなかった場合、警告が抑制されることはありません。 message は文字列のとき、 category は Warning のサブクラスでなければなりません。また message は Warning のインスタンスであってもよく、この場合 category は無視されます。
module_globals は、もし与えられるならば、警告が発せられるコードが使っているグローバル名前空間でなければなりません。(この引数は zipfile やその他の非ファイルシステムのインポート元の中にあるモジュールのソースを表示することをサポートするためのものです)
バージョン 2.5 で変更: module_globals 引数が追加されました
Python 3.x で廃止予定についてのwarningを発生させます。 Pythonが -3 オプション付きで実行されているときのみwarningが表示されます。 warn() と同じく、 message は文字列で、 category は Warninp のサブクラスである必要があります。 warnpy3k() は DeprecationWarning をデフォルトのwarningクラスとして利用しています。
警告をファイルに書き込みます。標準の実装では、 formatwarning(message, category, filename, lineno, line) を呼び出し、返された文字列を file に書き込みます。 file は標準では sys.stderr です。この関数は warnings.showwarning に別の実装を代入して置き換えることができます。 line はwarningメッセージに含めるソースコードの1行です。 line が与えられない場合、 showwarning() は filename と lineno から行を取得することを試みます。
バージョン 2.6 で変更: .. Added the line argument. Implementations that lack the new argument will trigger a DeprecationWarning. line 引数が追加されました。 新しい引数を使わない showwarning の実装は DeprecationWarning を発生させます。
警告を通常の方法で書式化します。返される文字列内には改行が埋め込まれている可能性があり、かつ文字列は改行で終端されています。 line はwarningメッセージに含まれるソースコードの1行です。 line が渡されない場合、 formatwarning() は filename と fileno から行の取得を試みます。
バージョン 2.6 で変更: line 引数を追加しました。
警告フィルタのリストにエントリを一つ挿入します。標準ではエントリは先頭に挿入されます; append が真ならば、末尾に挿入されます。 この関数は引数の型をチェックし、 message および module の正規表現をコンパイルしてから、これらをタプルにして警告フィルタ のリストに挿入します。二つのエントリが特定の警告に合致した場合、リストの先頭に近い方のエントリが後方にあるエントリに優先します。 引数が省略されると、標準では全てにマッチする値に設定されます。
単純なエントリを警告フィルタのリストに挿入します。引数の意味は filterwarnings() と同じですが、この関数により挿入されるフィ ルタはカテゴリと行番号が一致していれば全てのモジュールの全てのメッセージに合致しますので、正規表現は必要ありません。
警告フィルタをリセットします。これにより、 -W コマンドラインオプションによるもの simplefilter() 呼び出しによるものを含め、 filterwarnings() の呼び出しによる影響はすべて無効化されます。
コンテキストマネージャーで、warningフィルターと showwarning() 関数をコピーし、 終了時にリストアします。 record 引数が False (デフォルト値)だった場合、エントリー時には None を返します。もし record が True だった場合、カスタムの showwarning() 関数(この関数は同時に sys.stdout への出力を抑制します)によってオブジェクトが 継続的に追加されるリストを返します。 リストの中の各オブジェクトは、 showwarning() 関数の引数と同じ名前の属性を持っています。
module 引数は warnings を import して得られるオブジェクトの代わりに利用されます。 このモジュールのフィルターは保護されます。 この引数は、主に warnings モジュール自体をテストする目的で追加されました。
ノート
Python 3.0 では、 catch_warnings コンストラクタの引数は keyword-only 引数です。
バージョン 2.6 で追加.