warnで警告を表示させる

warnings.warn を使うと警告文を表示させることができる。

import warnings
warnings.warn('警告です')
print('hello world')  # プログラムは続行

実行するとstderrに警告文が表示されるものの、プログラムは停止せず、そのまま実行を継続する。

C:\temp\script.py:2: UserWarning: 警告です
  warnings.warn('警告です')
hello world

print関数とやっていることは同じように見えるかもしれないけど、warn は繰り返し実行しても、同じような警告は1回しか表示されないという利点がある。

import warnings

def foo():
    warnings.warn('警告です')
    print('hello world')

foo()
foo()
D:\temp\script.py:7: UserWarning: 警告です
  warnings.warn('警告です')
hello world
hello world


それから warn には stacklevel という引数があって、警告時に表示する場所を関数の呼び出し元に移動させることができる。

import warnings

def foo():
    warnings.warn('この関数を使わないでください', stacklevel=2)
    print('hello world')

for i in range(3):
    foo()
C:\temp\script.py:8: UserWarning: この関数を使わないでください
  foo()
hello world
hello world
hello world

stacklevel=2 としている理由は warn関数の内部から見て2回呼び出しをさかのぼるためである。


warn の第2引数 category にはクラス名を指定して、警告の種類を設定することができる。

warnings.warn('普通の警告', UserWarning)

よく使うクラスとしては DeprecationWarning がある。廃止された関数やモジュールを警告する時に使う。

import warnings

def foo():
    warnings.warn('この関数は廃止されました', DeprecationWarning, stacklevel=2)
    print('hello world')

for i in range(3):
    foo()
hello world
hello world
hello world

あれ? 警告が表示されないよ?
どういうことかというと、DeprecationWarning みたいに開発者向けの警告は初めから表示されないようになっているんだなあ。
この動作を変更するにはpythonのオプションを変更する。

python -W default script.py
# 以下は上の省略形
python -Wd script.py

毎回オプションをつけるのが面倒な場合は、PYTHONWARNINGS という名前の環境変数を作って default と書いておく方法もある。
設定した状態で普段使っているスクリプトを実行すると思わぬ発見があるかも。自分はこれで廃止予定になっているライブラリを使っていることに何度か気づいたことがある。


表示されない警告の種類はPythonのバージョンによって違う。最新の Python 3.4.2 だとこんな感じ。

import warnings
for i in warnings.filters:
    print(i)
('ignore', None, , None, 0)
('ignore', None, , None, 0)
('ignore', None, , None, 0)
('ignore', None, , None, 0)
('ignore', None, , None, 0)

DeprecationWarning の他にも表示されない警告があるね。

こいつらはフィルターと呼ばれていて、警告が発せられると上からマッチするものがないか見ていく。マッチするフィルターがあれば警告を無視(ignore)したりエラー(error)にしたりと所定の操作を実行する。

特定のモジュールやメッセージを限定したフィルターも書けるけど、まぁ普通は使わないと思う。興味があれば参考文献をどうぞ。

参考文献

warnings — Non-fatal alerts - Python Module of the Week
フィルターの書き方や警告の表示方法について
29.5. warnings — 警告の制御 — Python 3.4.2 ドキュメント
warningsの公式ドキュメント