note.nkmk.me

Pythonのwarningsで警告(Warning)を非表示、例外化

Date: 2019-09-18 / tags: Python, エラー

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()を使う。

なお、最初からすべての警告を非表示にして無視するのはおすすめしない。あくまでも警告が発生することを認識して原因を理解した上で、例えば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に警告カテゴリを指定可能。FutureWarningDeprecationWarning, 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.
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事