pythonでwarningをデバッグする際にpdbのソースコードデバッガでcatchしてくれると、とても便利ですよね。 例えば下記のコードを実行すると
import numpy as np x = np.ones((2, 2), dtype=np.float16) x[0, 0] = 1e4 y = x ** 2
$ python tmp.py /Users/tateiwa/nlp/src/tmp.py:5: RuntimeWarning: overflow encountered in square y = x ** 2
というwarningが表示されます。 (本筋ではないですが、この場合はnp.float16で定義されたnumpy array xを2乗することで[0,0]成分がその有効範囲を超えてしまうことが原因です)
このwarningをcatchする方法を2通り紹介します。
方法1: -W error オプション
pythonのオプションとして、-W errorオプションとともにpdbを実行すると、warningをexceptionとしてcatchされます。 これは実行時のオプションを変えるだけなので、楽ですね。
$ python -W error -m pdb -c "c" tmp.py Traceback (most recent call last): File "/usr/local/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/pdb.py", line 1726, in main pdb.runscript(mainpyfile) File "/usr/local/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/pdb.py", line 1586, in runscript self.run(statement) File "/usr/local/Cellar/python@3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/bdb.py", line 580, in run exec(cmd, globals, locals) File "<string>", line 1, in <module> File "/Users/tateiwa/nlp/src/tmp.py", line 1, in <module> import numpy as np RuntimeWarning: overflow encountered in square Uncaught exception. Entering post mortem debugging Running 'cont' or 'step' will restart the program > /hogehoge/tmp.py(1)<module>() -> import numpy as np (Pdb) l 1 -> import numpy as np 2 3 x = np.ones((2, 2), dtype=np.float16) 4 x[0, 0] = 1e4 5 >> y = x ** 2 6
[EOF]
ちなみに-W errorオプションをつけないと、下記のようにサラッと流れてしまいます。
python -m pdb -c "c" tmp.py /Users/tateiwa/nlp/src/tmp.py:1: RuntimeWarning: overflow encountered in square import numpy as np The program finished and will be restarted > /Users/tateiwa/nlp/src/tmp.py(1)<module>() -> import numpy as np
このオプションは https://docs.python.org/ja/3/using/cmdline.html#cmdoption-W にあるように、warningに関する実行時のオプションです。
方法2: warnings.filterwarnings
こちらはソースコードを変更する方法です。
import numpy as npx = np.ones((2, 2), dtype=np.float16) x[0, 0] = 1e4
import warnings with warnings.catch_warnings(): warnings.filterwarnings('error') try: y = x ** 2 except Warning as e: raise Exception(e)
実行すると、
$ python tmp.py
Traceback (most recent call last): File "/Users/tateiwa/nlp/src/tmp.py", line 11, in <module> y = x ** 2 RuntimeWarning: overflow encountered in squareDuring handling of the above exception, another exception occurred:
Traceback (most recent call last): File "/Users/tateiwa/nlp/src/tmp.py", line 13, in <module> raise Exception(e) Exception: overflow encountered in square
とちゃんとcatchしてくれていますね。 ちなみに, warnings.filterwarningsの引数を変えることで、catchする範囲を変更することができます。