Python logging levels can be registered using logging.addLevelName. Is there a method to obtain the Python logging number from a level name?
-
4Just to make sure: You did notice that the documentation on this function says "Defining your own levels is possible, but should not be necessary, as the existing levels have been chosen on the basis of practical experience. However, if you are convinced that you need custom levels, great care should be exercised when doing this…"abarnert– abarnert2013-08-23 00:23:33 +00:00Commented Aug 23, 2013 at 0:23
Add a comment
|
3 Answers
After you call addLevelName, the resulting level is treated exactly the same as all of the standard ones:
>>> import logging
>>> logging.getLevelName(10)
'DEBUG'
>>> logging.getLevelName('DEBUG')
10
>>> logging.addLevelName(15, 'DEBUGGISH')
>>> logging.getLevelName(15)
'DEBUGGISH'
>>> logging.getLevelName('DEBUGGISH')
15
The fact that getLevelName can map names to numbers as well as numbers to names is not actually documented in Python 2.x, nor does the name give any hint that it should… but a quick look at the source shows why it works.
10 Comments
user2357112
Looks documented to me. "If a numeric value corresponding to one of the defined levels is passed in, the corresponding string representation is returned."
abarnert
@user2357112: It's the other way around that isn't documented, where you pass in a string and get back the corresponding number.
torek
It would be nice if the logging module officially exported a table of names.
[k for k in logging._levelNames if isinstance(k, basestring)] works, but, bleh. :-)abarnert
@torek: I think it would be cleaner if it kept separate dicts for names-for-numbers and numbers-to-names, and had a
getLevelNumber(name) function alongside the getLevelName(number) function. IIRC, the clever hack that motivated this single-dict design in the pre-stdlib module isn't even there anymore.gerardw
Update: the current / 3.6 documentation notes: 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.
|
Surprisingly late, since Python 3.11 you can and maybe should start using: logging.getLevelNamesMapping
import logging
assert logging.INFO == logging.getLevelNamesMapping()["INFO"]
logging.addLevelName(logging.INFO + 5, "IMPORTANT")
assert logging.INFO + 5 == logging.getLevelNamesMapping()["IMPORTANT"]
Why, >maybe< should.
- The double mapping of
getLevelNamewas a (nice?) mistake back in Python 2. Shortly removed in 3.4.0..1. pyright therefore also reports thegetLevelName("some_string")usage as deprecated. So you end up with warnings if you use it (reportDeprecatedoption active), but also the opinion of pyright. - Semantically it is not intuitive, why should getLevelName return an integer? The new function is more intuitive, but slightly more expensive as it copies the underlying dict.
logging.getLevelNamesMapping()["invalid"]will raise aKeyErrorif input a wrong level name, withgetLevelName("invalid") -> "Level invalid". Of course that is both an advantage and disadvantage at the same time.