Pythonのwarningsで警告(Warning)を非表示、例外化
Pythonのライブラリで廃止予定の関数を使った場合などに警告(Warning)が出力されることがある。警告を非表示にしたり、例外として扱って処理を止めるようにしたりするには、標準ライブラリのwarningsモジュールを使う。
ここでは以下の内容について説明する。
- 警告(Warning)の例
- 警告を非表示
- すべての警告を表示させない
- 非表示にするカテゴリを指定
- 警告を例外として扱う
- 一時的に警告を制御
warningsモジュールには警告を発するための関数warn()
などもあるが、ここでは触れない。自作の関数などの中で警告を発したいような場合は上記の公式ドキュメントを参照されたい。
警告(Warning)の例
pandasのix[]
によるFutureWarning
とchained assignmentによるSettingWithCopyWarning
を例とする。
import warnings
import pandas as pd
df = pd.DataFrame([[0, 1, 2], [3, 4, 5]])
df.ix[0, 0] = 0
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:1: FutureWarning:
# .ix is deprecated. Please use
# .loc for label based indexing or
# .iloc for positional indexing
#
# See the documentation here:
# http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#ix-indexer-is-deprecated
# """Entry point for launching an IPython kernel.
df.iloc[:1][0] = 0
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning:
# A value is trying to be set on a copy of a slice from a DataFrame.
# Try using .loc[row_indexer,col_indexer] = value instead
#
# See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
# """Entry point for launching an IPython kernel.
なお、ix[]
がFutureWarning
になったのはpandas0.25.0
から。それより前はDeprecationWarning
だった。
それぞれの警告については以下の記事を参照。
警告を非表示
警告の扱いを変更するにはwarnings.simplefilter()
、変更した設定をデフォルトに戻す(リセットする)にはwarnings.resetwarnings()
を使う。
- warnings.simplefilter() --- 警告の制御 — Python 3.7.4 ドキュメント
- warnings.resetwarnings() --- 警告の制御 — Python 3.7.4 ドキュメント
なお、最初からすべての警告を非表示にして無視するのはおすすめしない。あくまでも警告が発生することを認識して原因を理解した上で、例えばJupyter Notebook(IPython Notebook)の出力をスッキリさせたいというような状況でのみ非表示にするべき。
すべての警告を表示させない
warnings.simplefilter()
の第一引数action
を'ignore'
とするとすべての警告が非表示になる。
warnings.simplefilter('ignore')
df.ix[0, 0] = 0
df.iloc[:1][0] = 0
第一引数action
には'ignore'
のほか、警告を例外として扱う'error'
などもある。
'error'
については後述。
非表示にするカテゴリを指定
warnings.simplefilter()
の第二引数category
に警告カテゴリを指定可能。FutureWarning
やDeprecationWarning
, SyntaxWarning
, RuntimeWarning
などがある。
第二引数category
のデフォルトは、すべての警告カテゴリクラスの基底クラスWarning
。上の例のように、デフォルトではすべての警告が対象となる。
警告カテゴリは警告メッセージに記述されている。上述のようにix[]
はFutureWarning
でchained assignmentはSettingWithCopyWarning
。
例えばcategory=FutureWarning
とすると、ix[]
の警告は非表示になるがchained assignmentによる警告はそのまま。
warnings.resetwarnings()
warnings.simplefilter('ignore', FutureWarning)
df.ix[0, 0] = 0
df.iloc[:1][0] = 0
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning:
# A value is trying to be set on a copy of a slice from a DataFrame.
# Try using .loc[row_indexer,col_indexer] = value instead
#
# See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
# """Entry point for launching an IPython kernel.
chained assignmentによる警告のカテゴリSettingWithCopyWarning
はpandasで独自に定義されたものなので、そのまま指定するとエラーとなる。ライブラリ内で定義されたカテゴリクラスを読み込んで指定しなければならない。
warnings.resetwarnings()
# warnings.simplefilter('ignore', SettingWithCopyWarning)
# NameError: name 'SettingWithCopyWarning' is not defined
warnings.simplefilter('ignore', pd.core.common.SettingWithCopyWarning)
df.ix[0, 0] = 0
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:1: FutureWarning:
# .ix is deprecated. Please use
# .loc for label based indexing or
# .iloc for positional indexing
#
# See the documentation here:
# http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#ix-indexer-is-deprecated
# """Entry point for launching an IPython kernel.
df.iloc[:1][0] = 0
警告を例外として扱う
警告が発生しても処理は止まることなく実行される。厳格に、警告でも例外のように処理を止めたいという場合は、warnings.simplefilter()
の第一引数action
を'error'
とする。
warnings.resetwarnings()
warnings.simplefilter('error')
# df.ix[0, 0] = 0
# FutureWarning: ...
ここでは便宜上コメントアウトしているが、実際にコードを実行すると警告が発生した時点でプログラムが途中終了する。
'ignore'
で非表示にする場合と同じく、第二引数category
で対象とする警告カテゴリを指定できる。カテゴリごとに別々のアクションを指定することも可能。
warnings.resetwarnings()
warnings.simplefilter('ignore', FutureWarning)
warnings.simplefilter('error', pd.core.common.SettingWithCopyWarning)
df.ix[0, 0] = 0
# df.iloc[:1][0] = 0
# SettingWithCopyWarning: ...
便宜上、例外となるコードはコメントアウトしている。
一時的に警告を制御
一時的に警告を制御したい場合は、with
ブロックとwarnings.catch_warnings()
を使う。
with
ブロック内でのみwarnings.simplefilter()
による変更が有効になる。ブロックの外ではそのまま。
warnings.resetwarnings()
with warnings.catch_warnings():
warnings.simplefilter('ignore')
df.ix[0, 0] = 0
df.ix[0, 0] = 0
# /usr/local/lib/python3.7/site-packages/ipykernel_launcher.py:1: FutureWarning:
# .ix is deprecated. Please use
# .loc for label based indexing or
# .iloc for positional indexing
#
# See the documentation here:
# http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#ix-indexer-is-deprecated
# """Entry point for launching an IPython kernel.