public note

Python logging levelを示す数値とその名称はlogging.getLevelNameで相互変換できる

結論

Python の logging.getLevelName 関数で、ログレベルを表す数値とその名称に当たる文字列を相互変換することができます。関数名の印象だと 数値 -> 名称 の一方向っぽいのですが 、実は双方向で変換できます。

$ python
Python 3.8.11 (default, Jul 31 2021, 13:16:16) 
[Clang 12.0.5 (clang-1205.0.22.11)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import logging
>>> logging.getLevelName('DEBUG')
10
>>> type(logging.getLevelName('DEBUG'))
<class 'int'>
>>> logging.getLevelName(logging.DEBUG)
'DEBUG'
>>> type(logging.getLevelName(logging.DEBUG))
<class 'str'>

ドキュメント

https://docs.python.org/3/library/logging.html#logging.getLevelName

Returns the textual or numeric representation of logging level level.

背景

Python の logging モジュールでは、デフォルトのログレベルを以下のように定義しています。

CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

https://github.com/python/cpython/blob/ae5259171b8ef62165e061b9dea7ad645a5131a2/Lib/logging/__init__.py#L91-L98

下記のように、logging モジュールから INT 型で取得できます。

>>> logging.DEBUG
10
>>> type(logging.DEBUG)
<class 'int'>

この数値で表現されるログレベルを、 'DEBUG' のようなレベル名称から取得したい場合にも logging.getLevelName が使えます。

実装されている関数名だけを眺めると、名称 -> 数値 の関数が用意されていないように見えるためか、if文やdictで自前で変換する手法をよく見かけます。もっとスマートな方法があるはずだけどな、と私も長いこと思っていました。

本来は getLevel のような関数が存在するのが適当かと思いますが、Python 3.4以前との後方互換性を維持するために、このような仕様になっているそうです。

Changed in version 3.4: In Python versions earlier than 3.4, this function could also be passed a text level, and would return the corresponding numeric value of the level. This undocumented behaviour was considered a mistake, and was removed in Python 3.4, but reinstated in 3.4.2 due to retain backward compatibility.