When trying to load the following config file, I get an error ``ConfigParser.NoOptionError: No option 'handlers' in section: 'logger_0'`` (in both Python 2.6.4 and Python 3.1.1 on OSX, obviously ConfigParser is spelled configparser in 3.1):
[loggers] keys=root,0 [handlers] keys=console [formatters] keys=simple [logger_root] handlers=console [logger_0] level=DEBUG qualname=0 [handler_console] class=StreamHandler formatter=simple args=() [formatter_simple] format=%(asctime)s:%(levelname)-8s:%(name)s::%(message)s the goal is simply to have a logging level different on ``0`` than it is on ``root``, but to get it I have to include a handler on ``0`` and stop propagation (or messages are displayed on both root and 0). Do note that this behavior (of mandating handlers) does *not* happen when loggers are configured programmatically. Should this be considered a bug? Worthy of opening a request on the tracker? And while I'm at it, a few other oddities/annoyances I noticed in logging: * have to specify the `root` logger in loggers/keys, even though it's mandatory to configure the root logger, or I get the following error:: Traceback (most recent call last): File "test.py", line 6, in <module> logging.config.fileConfig('logging.conf') File "/opt/local/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/logging/config.py", line 82, in fileConfig _install_loggers(cp, handlers, disable_existing_loggers) File "/opt/local/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/logging/config.py", line 183, in _install_loggers llist.remove("root") ValueError: list.remove(x): x not in list * the ``args`` option is required when defining a handler, even in the example above where the handler doesn't take any argument (mandatory ones, anyway) * Logger.log() doesn't take level names, only numerical levels, even after having called ``addLevelName``. This makes logging with custom levels much less clear as one has to write something along the lines of ``logging.log(100, 'Houston, we have a problem')`` instead of the clearer ``logging.log('PANTS_ON_FIRE', 'Houston, we have a problem')``. Note that since the introduction of _checkLevel fixing that is trivial: diff -r dafc54104884 Lib/logging/__init__.py --- a/Lib/logging/__init__.py Sun Jan 31 14:17:25 2010 +0100 +++ b/Lib/logging/__init__.py Mon Feb 01 22:21:03 2010 +0100 @@ -1146,13 +1146,14 @@ logger.log(level, "We have a %s", "mysterious problem", exc_info=1) """ - if not isinstance(level, int): + try: + rv = _checkLevel(level) + except (TypeError, ValueError): if raiseExceptions: - raise TypeError("level must be an integer") - else: - return - if self.isEnabledFor(level): - self._log(level, msg, args, **kwargs) + raise + + if self.isEnabledFor(rv): + self._log(rv, msg, args, **kwargs) def findCaller(self): """ -- http://mail.python.org/mailman/listinfo/python-list