[Python-checkins] r87183 - python/branches/py3k/Doc/library/logging.rst

vinay.sajip python-checkins at python.org
Sun Dec 12 18:37:28 CET 2010


Author: vinay.sajip
Date: Sun Dec 12 18:37:27 2010
New Revision: 87183

Log:
Logging documentation - further update.

Modified:
   python/branches/py3k/Doc/library/logging.rst

Modified: python/branches/py3k/Doc/library/logging.rst
==============================================================================
--- python/branches/py3k/Doc/library/logging.rst	(original)
+++ python/branches/py3k/Doc/library/logging.rst	Sun Dec 12 18:37:27 2010
@@ -48,7 +48,7 @@
 +-------------------------------------+--------------------------------------+
 | Report events that occur during     | logging.info() (or logging.debug()   |
 | normal operation of a program (e.g. | for very detailed output for         |
-| or status monitoring or fault       | diagnostic purposes)                 |
+| for status monitoring or fault      | diagnostic purposes)                 |
 | investigation)                      |                                      |
 +-------------------------------------+--------------------------------------+
 | Issue a warning regarding a         | warnings.warn() in library code      |
@@ -283,12 +283,12 @@
 :func:`time.strftime`.
 
 
-Er...that's it for the tutorial
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Er...that's it for the basics
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-That concludes the tutorial. It should be enough to get you up and running
-with logging. There's a lot more that the logging package offers, but to get
-the best out of it, you'll need to invest a little more of your time in
+That concludes the basic tutorial. It should be enough to get you up and
+running with logging. There's a lot more that the logging package offers, but
+to get the best out of it, you'll need to invest a little more of your time in
 reading the following sections. If you're ready for that, grab some of your
 favourite beverage and carry on.
 
@@ -298,11 +298,14 @@
 group (available at http://groups.google.com/group/comp.lang.python) and you
 should receive help before too long.
 
-Still here? There's no need to read this long page in linear fashion, top to
-bottom. Take a look at the topics in the sidebar to see if there's something
-that interests you, and click on a topic to see more detail. Although some of
-the topics do follow on from each other, there are a few that can just stand
-alone.
+Still here? There's no need to read the whole of the logging documentation in
+linear fashion, top to bottom (there's quite a lot of it still to come). You
+can carry on reading the next few sections, which provide a slightly more
+advanced/in-depth tutorial than the basic one above. After that, you can
+take a look at the topics in the sidebar to see if there's something that
+especially interests you, and click on a topic to see more detail. Although
+some of the topics do follow on from each other, there are a few that can just
+stand alone.
 
 
 .. _more-advanced-logging:
@@ -374,14 +377,24 @@
 The most widely used methods on logger objects fall into two categories:
 configuration and message sending.
 
+These are the most common configuration methods:
+
 * :meth:`Logger.setLevel` specifies the lowest-severity log message a logger
-  will handle, where debug is the lowest built-in severity level and critical is
-  the highest built-in severity.  For example, if the severity level is info,
-  the logger will handle only info, warning, error, and critical messages and
-  will ignore debug messages.
+  will handle, where debug is the lowest built-in severity level and critical
+  is the highest built-in severity.  For example, if the severity level is
+  INFO, the logger will handle only INFO, WARNING, ERROR, and CRITICAL messages
+  and will ignore DEBUG messages.
+
+* :meth:`Logger.addHandler` and :meth:`Logger.removeHandler` add and remove
+  handler objects from the logger object.  Handlers are covered in more detail
+  in :ref:`handler-basic`.
 
 * :meth:`Logger.addFilter` and :meth:`Logger.removeFilter` add and remove filter
-  objects from the logger object.  This tutorial does not address filters.
+  objects from the logger object.  Filters are covered in more detail in
+  :ref:`filter`.
+
+You don't need to always call these methods on every logger you create. See the
+last two paragraphs in this section.
 
 With the logger object configured, the following methods create log messages:
 
@@ -410,11 +423,24 @@
 down in the hierarchical list are children of loggers higher up in the list.
 For example, given a logger with a name of ``foo``, loggers with names of
 ``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all descendants of ``foo``.
+
+Loggers have a concept of *effective level*. If a level is not explicitly set
+on a logger, the level of its parent is used instead as its effective level.
+If the parent has no explicit level set, *its* parent is examined, and so on -
+all ancestors are searched until an explicitly set level is found. The root
+logger always has an explicit level set (``WARNING`` by default). When deciding
+whether to process an event, the effective level of the logger is used to
+determine whether the event is passed to the logger's handlers.
+
 Child loggers propagate messages up to the handlers associated with their
-ancestor loggers.  Because of this, it is unnecessary to define and configure
+ancestor loggers. Because of this, it is unnecessary to define and configure
 handlers for all the loggers an application uses. It is sufficient to
 configure handlers for a top-level logger and create child loggers as needed.
+(You can, however, turn off propagation by setting the *propagate*
+attribute of a logger to *False*.)
+
 
+.. _handler-basic:
 
 Handlers
 ^^^^^^^^
@@ -428,8 +454,9 @@
 requires three individual handlers where each handler is responsible for sending
 messages of a specific severity to a specific location.
 
-The standard library includes quite a few handler types; this tutorial uses only
-:class:`StreamHandler` and :class:`FileHandler` in its examples.
+The standard library includes quite a few handler types (see
+:ref:`useful-handlers`); the tutorials use mainly :class:`StreamHandler` and
+:class:`FileHandler` in its examples.
 
 There are very few methods in a handler for application developers to concern
 themselves with.  The only handler methods that seem relevant for application
@@ -656,46 +683,70 @@
 For more information about logging using a dictionary, see
 :ref:`logging-config-api`.
 
-.. _library-config:
+What happens if no configuration is provided
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Configuring Logging for a Library
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+If no logging configuration is provided, it is possible to have a situation
+where a logging event needs to be output, but no handlers can be found to
+output the event. The behaviour of the logging package in these
+circumstances is dependent on the Python version.
+
+For versions of Python prior to 3.2, the behaviour is as follows:
+
+* If *logging.raiseExceptions* is *False* (production mode), the event is
+  silently dropped.
+
+* If *logging.raiseExceptions* is *True* (development mode), a message
+  "No handlers could be found for logger X.Y.Z" is printed once.
+
+In Python 3.2 and later, the behaviour is as follows:
+
+* The event is output using a 'handler of last resort", stored in
+  ``logging.lastResort``. This internal handler is not associated with any
+  logger, and acts like a :class:`StreamHandler` which writes the event
+  description message to the current value of ``sys.stderr`` (therefore
+  respecting any redirections which may be in effect). No formatting is
+  done on the message - just the bare event description message is printed.
+  The handler's level is set to ``WARNING``, so all events at this and
+  greater severities will be output.
 
-When developing a library which uses logging, some consideration needs to be
-given to its configuration. If the using application does not use logging, and
-library code makes logging calls, then a one-off message "No handlers could be
-found for logger X.Y.Z" is printed to the console. This message is intended
-to catch mistakes in logging configuration, but will confuse an application
-developer who is not aware of logging by the library.
-
-In addition to documenting how a library uses logging, a good way to configure
-library logging so that it does not cause a spurious message is to add a
-handler which does nothing. This avoids the message being printed, since a
-handler will be found: it just doesn't produce any output. If the library user
-configures logging for application use, presumably that configuration will add
-some handlers, and if levels are suitably configured then logging calls made
-in library code will send output to those handlers, as normal.
+To obtain the pre-3.2 behaviour, ``logging.lastResort`` can be set to *None*.
 
-A do-nothing handler can be simply defined as follows::
+.. _library-config:
 
-    import logging
+Configuring Logging for a Library
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-    class NullHandler(logging.Handler):
-        def emit(self, record):
-            pass
-
-An instance of this handler should be added to the top-level logger of the
-logging namespace used by the library. If all logging by a library *foo* is
-done using loggers with names matching "foo.x.y", then the code::
+When developing a library which uses logging, you should take care to
+document how the library uses logging - for example, the names of loggers
+used. Some consideration also needs to be given to its logging configuration.
+If the using application does not use logging, and library code makes logging
+calls, then (as described in the previous section) events of severity
+``WARNING`` and greater will be printed to ``sys.stderr``. This is regarded as
+the best default behaviour.
+
+If for some reason you *don't* want these messages printed in the absence of
+any logging configuration, you can attach a do-nothing handler to the top-level
+logger for your library. This avoids the message being printed, since a handler
+will be always be found for the library's events: it just doesn't produce any
+output. If the library user configures logging for application use, presumably
+that configuration will add some handlers, and if levels are suitably
+configured then logging calls made in library code will send output to those
+handlers, as normal.
+
+A do-nothing handler is included in the logging package: :class:`NullHandler`
+(since Python 3.1). An instance of this handler could be added to the top-level
+logger of the logging namespace used by the library (*if* you want to prevent
+your library's logged events being output to ``sys.stderr`` in the absence of
+logging configuration). If all logging by a library *foo* is done using loggers
+with names matching 'foo.x', 'foo.x.y', etc. then the code::
 
     import logging
-
-    h = NullHandler()
-    logging.getLogger("foo").addHandler(h)
+    logging.getLogger('foo').addHandler(logging.NullHandler())
 
 should have the desired effect. If an organisation produces a number of
-libraries, then the logger name specified can be "orgname.foo" rather than
-just "foo".
+libraries, then the logger name specified can be 'orgname.foo' rather than
+just 'foo'.
 
 **PLEASE NOTE:** It is strongly advised that you *do not add any handlers other
 than* :class:`NullHandler` *to your library's loggers*. This is because the
@@ -705,9 +756,6 @@
 "under the hood", you might well interfere with their ability to carry out
 unit tests and deliver logs which suit their requirements.
 
-.. versionadded:: 3.1
-   The :class:`NullHandler` class.
-
 
 Logging Levels
 --------------
@@ -781,6 +829,8 @@
 given numeric value might mean different things for different libraries.
 
 
+.. _useful-handlers:
+
 Useful Handlers
 ---------------
 


More information about the Python-checkins mailing list