\section{\module{warnings} ---
         警告の制御}

\declaremodule{standard}{warnings}
\modulesynopsis{警告メッセージを送出したり、その処理方法を制御したり
します。}
\index{warnings}

\versionadded{2.1}

警告メッセージは一般に、ユーザに警告しておいた方がよいような状況下に
プログラムが置かれているが、その状況は (通常は) 例外を送出したり
そのプログラムを終了させるほどの正当な理由がないといった状況で
発されます。例えば、プログラムが古いモジュールを使っている場合
には警告を発したくなるかもしれません。

Python プログラマは、このモジュールの \function{warn()} 関数を
使うことで警告を発することができます。(C 言語のプログラマは
\cfunction{PyErr_Warn()} を使います; 詳細は
\citetitle[../api/exceptionHandling.html]{Python/C API Reference
Manual} を参照してください)。

警告メッセージは通常 \code{sys.stderr} に出力されますが、その処理
方法は、全ての警告に対する無視する処理から警告を例外に変更する
処理まで、柔軟に変更することができます。警告の処理方法は
警告カテゴリ (以下参照)、警告メッセージテキスト、そして警告を
発したソースコード上の場所に基づいて変更することができます。
ソースコード上の同じ場所に対して特定の警告が繰り返された場合、
通常は抑制されます。

警告制御には 2 つの段階 (stage) があります: 第一に、警告が発される
たびに、メッセージを出力すべきかどうか決定が行われます; 次に、
メッセージを出力するなら、メッセージはユーザによって設定が可能なフック
を使って書式化され印字されます。

警告メッセージを出力するかどうかの決定は、警告フィルタによって制御
されます。警告フィルタは一致規則 (matching rule)と動作からなるシーケンスです。
\function{filterwarnings()} を呼び出して一致規則をフィルタに追加する
ことができ、\function{resetwarnings()} を呼び出してフィルタを標準
設定の状態にリセットすることができます。

警告メッセージの印字は \function{showwarning()} を呼び出して行うことが
でき、この関数は上書きすることができます; この関数の標準の実装では、
\function{formatwarning()} を呼び出して警告メッセージを書式化しますが、
この関数についても自作の実装を使うことができます。


\subsection{警告カテゴリ \label{warning-categories}}

警告カテゴリを表現する組み込み例外は数多くあります。このカテゴリ化は
警告をグループごとフィルタする上で便利です。現在以下の警告カテゴリ
クラスが定義されています:

\begin{tableii}{l|l}{exception}{クラス}{記述}

\lineii{Warning}{全ての警告カテゴリクラスの基底クラスです。
\exception{Exception} のサブクラスです。}

\lineii{UserWarning}{\function{warn()} の標準のカテゴリです。}

\lineii{DeprecationWarning}{その機能が廃用化されていることを示す
警告カテゴリの基底クラスです。}

\lineii{SyntaxWarning}{その文法機能があいまいであることを示す警告
カテゴリの基底クラスです。}

\lineii{RuntimeWarning}{その実行時システム機能があいまいであることを
示す警告カテゴリの基底クラスです。}

\lineii{FutureWarning}{その構文の意味付けが将来変更される予定である
ことを示す警告カテゴリの基底クラスです。}

\lineii{PendingDeprecationWarning}{将来その機能が廃用化されることを示す
警告カテゴリの基底クラスです(デフォルトでは無視されます)。}

\lineii{ImportWarning}{モジュールのインポート処理中に引き起こされる
警告カテゴリの基底クラスです(デフォルトでは無視されます)。}

\lineii{UnicodeWarning}{Unicode に関係した警告カテゴリの基底クラスです。}

\end{tableii}

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

標準の警告カテゴリをユーザの作成したコード上でサブクラス化することで、
さらに別の警告カテゴリを定義することができます。
警告カテゴリは常に \exception{Warning} クラスのサブクラスでなければ
なりません。


\subsection{警告フィルタ \label{warning-filter}}

警告フィルタは、ある警告を無視すべきか、表示すべきか、あるいは
(例外を送出する) エラーにするべきかを制御します。

概念的には、警告フィルタは複数のフィルタ仕様からなる順番付けられた
リストを維持しています; 何らかの特定の警告が生じると、フィルタ仕様の
一致するものが見つかるまで、リスト中の各フィルタとの照合が行われます;
一致したフィルタ仕様がその警告の処理方法を決定します。
フィルタの各エントリは
(\var{action}, \var{message}, \var{category}, \var{module},
\var{lineno}) からなるタプルです。ここで:

\begin{itemize}

\item \var{action} は以下の文字列のうちの一つです:

    \begin{tableii}{l|l}{code}{値}{処理方法}

    \lineii{"error"}{一致した警告を例外に変えます}

    \lineii{"ignore"}{一致した警告を決して出力しません}

    \lineii{"always"}{一致した警告を常に出力します}

    \lineii{"default"}{一致した警告のうち、警告の原因になった
ソースコード上の場所ごとに、最初の警告のみ出力します。}

    \lineii{"module"}{一致した警告のうち、警告の原因になった
モジュールごとに、最初の警告のみ出力します。}

    \lineii{"once"}{一致した警告のうち、警告の原因になった
場所にかかわらず最初の警告のみ出力します。}

    \end{tableii}

\item \var{message} は正規表現を含む文字列で、メッセージはこの
パタンに一致しなければなりません (照合時には常に大小文字の区別を
しないようにコンパイルされます)。

\item \var{category} はクラス (\exception{Warning} のサブクラス) です。
警告クラスはこのクラスのサブクラスに一致しなければなりません。

\item \var{module} は正規表現を含む文字列で、モジュール名はこのパタン
に一致しなければなりません (照合時には常に大小文字の区別を
しないようにコンパイルされます)。

\item \var{lineno} 整数で、警告が発生した場所の行番号に一致しなければ
なりません、すべての行に一致する場合には \code{0} になります。

\end{itemize}

\exception{Warning} クラスは組み込みの \exception{Exception} クラスから
導出されているので、警告をエラーに変えるには単に
\code{category(message)} を \code{raise} します。

警告フィルタは Python インタプリタのコマンドラインに渡される
\programopt{-W} オプションで初期化されます。インタプリタは
\programopt{-W} オプションに渡される全ての引数を
\code{sys.warnoptions}; に変換せずに保存します; \module{warnings}
モジュールは最初に \code{import} された際にこれらの引数を解釈します
(無効なオプションは\code{sys.stderr} にメッセージを出力した後
無視されます)。

デフォルトでは無視される警告を \programopt{-Wd} をインタプリタに渡すこ
とで有効にすることができます。このオプションは通常はデフォルトで無視さ
れるようなものを含む全ての警告のデフォルトでの扱いを有効化します。この
ような振る舞いは開発中のパッケージをインポートする問題をデバッグする時
にImportWarning を有効化するために使えます。ImportWarning は次のよう
な Python コードを使って明示的に有効化することもできます。

\begin{verbatim}
    warnings.simplefilter('default', ImportWarning)
\end{verbatim}


\subsection{利用可能な関数 \label{warning-functions}}

\begin{funcdesc}{warn}{message\optional{, category\optional{, stacklevel}}}
警告を発するか、無視するか、あるいは例外を送出します。
\var{category} 引数が与えられた場合、警告カテゴリクラスでなければ
なりません (上を参照してください); 標準の値は \exception{UserWarning}
です。\var{message} を \exception{Warning} インスタンスで代用する
こともできますが、この場合 \var{category} は無視され、
\code{message.__class__} が使われ、メッセージ文は \code{str(message)}
になります。発された例外が前述した警告フィルタによってエラーに
変更された場合、この関数は例外を送出します。引数 \var{stacklevel}
は Python でラッパ関数を書く際に利用することができます。例えば:

\begin{verbatim}
def deprecation(message):
    warnings.warn(message, DeprecationWarning, stacklevel=2)
\end{verbatim}

こうすることで、警告が参照するソースコード部分を、
\function{deprecation()} 自身ではなく \function{deprecation()} を
呼び出した側にできます (というのも、前者の場合は警告メッセージ
の目的を台無しにしてしまうからです)。
\end{funcdesc}

\begin{funcdesc}{warn_explicit}{message, category, filename,
 lineno\optional{, module\optional{, registry\optional{,
 module_globals}}}}
\function{warn()} の機能に対する低レベルのインタフェースで、
メッセージ、警告カテゴリ、ファイル名および行番号、そしてオプションの
モジュール名およびレジストリ情報 (モジュールの 
\code{__warningregistry__} 辞書) を明示的に渡します。
モジュール名は標準で \code{.py} が取り去られたファイル名になります;
レジストリが渡されなかった場合、警告が抑制されることはありません。
\var{message} は文字列のとき、\var{category} は \exception{Warning}
のサブクラスでなければなりません。また \var{message} は
\exception{Warning} のインスタンスであってもよく、この場合
\var{category} は無視されます。

\var{module_globals} は、もし与えられるならば、警告が発せられるコードが
使っているグローバル名前空間でなければなりません。(この引数は zipfile
やその他の非ファイルシステムのインポート元の中にあるモジュールのソース
を表示することをサポートするためのもので、Python 2.5 で追加されました。)
\end{funcdesc}

\begin{funcdesc}{showwarning}{message, category, filename,
			     lineno\optional{, file}}
警告をファイルに書き込みます。標準の実装では、
\code{formatwarning(\var{message}, \var{category}, \var{filename},
\var{lineno})} を呼び出し、返された文字列を \var{file} に書き込み
ます。\var{file} は標準では \code{sys.stderr} です。
この関数は \code{warnings.showwarning} に別の実装を代入して
置き換えることができます。
\end{funcdesc}

\begin{funcdesc}{formatwarning}{message, category, filename, lineno}
警告を通常の方法で書式化します。返される文字列内には改行が埋め込まれて
いる可能性があり、かつ文字列は改行で終端されています。
\end{funcdesc}

\begin{funcdesc}{filterwarnings}{action\optional{,
                 message\optional{, category\optional{,
                 module\optional{, lineno\optional{, append}}}}}}
警告フィルタのリストにエントリを一つ挿入します。標準ではエントリは
先頭に挿入されます; \var{append} が真ならば、末尾に挿入されます。
この関数は引数の型をチェックし、\var{message} および \var{module}
の正規表現をコンパイルしてから、これらをタプルにして警告フィルタ
のリストに挿入します。二つのエントリが特定の警告に合致した場合、
リストの先頭に近い方のエントリが後方にあるエントリに優先します。
引数が省略されると、標準では全てにマッチする値に設定されます。
\end{funcdesc}

\begin{funcdesc}{simplefilter}{action\optional{,
                 category\optional{,
                 lineno\optional{, append}}}}
単純なエントリを警告フィルタのリストに挿入します。引数の意味
は \function{filterwarnings()} と同じですが、この関数により挿入されるフィ
ルタはカテゴリと行番号が一致していれば全てのモジュールの全てのメッセー
ジに合致しますので、正規表現は必要ありません。
\end{funcdesc}

\begin{funcdesc}{resetwarnings}{}
警告フィルタをリセットします。これにより、\programopt{-W} コマンドラ
インオプションによるもの \function{simplefilter()} 呼び出しによるもの
を含め、\function{filterwarnings} の呼び出しによる影響はすべて無効化
されます。
\end{funcdesc}
