40

Python logging levels can be registered using logging.addLevelName. Is there a method to obtain the Python logging number from a level name?

Casebash
  • 114,675
  • 90
  • 247
  • 350
  • 4
    Just to make sure: You did notice that [the documentation on this function](http://docs.python.org/2/howto/logging.html#custom-levels) 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 Aug 23 '13 at 00:23

2 Answers2

53

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.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Looks documented to me. "If a numeric value corresponding to one of the defined levels is passed in, the corresponding string representation is returned." – user2357112 Aug 23 '13 at 00:30
  • 3
    @user2357112: It's the other way around that isn't documented, where you pass in a string and get back the corresponding number. – abarnert Aug 23 '13 at 00:45
  • 2
    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. :-) – torek Aug 23 '13 at 00:51
  • 2
    @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. – abarnert Aug 23 '13 at 00:55
  • @torek: Also, notice that [the module itself](http://hg.python.org/cpython/file/2.7/Lib/logging/__init__.py#l182) does an even worse hack than yours, checking `str(level) == level` to verify that it's a string. – abarnert Aug 23 '13 at 00:57
  • Update: the [current / 3.6](https://docs.python.org/3/library/logging.html) 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._ – gerardw Dec 26 '16 at 16:01
  • It's a bit of a contest as to which is more inapproprate. Using the private table logging._levelNames, or using the undocumented behavior of logging.getLevelName(). But it's worth noting that loggin.getLevelName("random junk") it returns 'Level random junk". – Ben Hyde Jan 30 '19 at 17:00
0

If you can deal with a default level, checking the type of the result is a decent workaround.

int_level = logging.getLevelName(string_level)
  if type(int_level) != int:
    int_level = 20 # default to INFO
apardoe
  • 631
  • 6
  • 10