summaryrefslogtreecommitdiffstats
path: root/Doc/library
diff options
context:
space:
mode:
authorNir Friedman <quicknir@gmail.com>2024-03-13 15:58:30 (GMT)
committerGitHub <noreply@github.com>2024-03-13 15:58:30 (GMT)
commit7f418fb111dec325b5c9fe6f6e96076049322f02 (patch)
tree2731449eb28af73b7436aa083d3bba78e0da4746 /Doc/library
parent8e2aab7ad5e1c8b3360c1e1b80ddadc0845eaa3e (diff)
downloadcpython-7f418fb111dec325b5c9fe6f6e96076049322f02.zip
cpython-7f418fb111dec325b5c9fe6f6e96076049322f02.tar.gz
cpython-7f418fb111dec325b5c9fe6f6e96076049322f02.tar.bz2
gh-98731: Improvements to the logging documentation (GH-101618)
Co-authored-by: Vinay Sajip <vinay_sajip@yahoo.co.uk>
Diffstat (limited to 'Doc/library')
-rw-r--r--Doc/library/logging.rst152
1 files changed, 67 insertions, 85 deletions
diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst
index e38b743..4e7d18b 100644
--- a/Doc/library/logging.rst
+++ b/Doc/library/logging.rst
@@ -30,13 +30,53 @@ is that all Python modules can participate in logging, so your application log
can include your own messages integrated with messages from third-party
modules.
-The simplest example:
+Here's a simple example of idiomatic usage: ::
+
+ # myapp.py
+ import logging
+ import mylib
+ logger = logging.getLogger(__name__)
+
+ def main():
+ logging.basicConfig(filename='myapp.log', level=logging.INFO)
+ logger.info('Started')
+ mylib.do_something()
+ logger.info('Finished')
+
+ if __name__ == '__main__':
+ main()
+
+::
+
+ # mylib.py
+ import logging
+ logger = logging.getLogger(__name__)
+
+ def do_something():
+ logger.info('Doing something')
+
+If you run *myapp.py*, you should see this in *myapp.log*:
.. code-block:: none
- >>> import logging
- >>> logging.warning('Watch out!')
- WARNING:root:Watch out!
+ INFO:__main__:Started
+ INFO:mylib:Doing something
+ INFO:__main__:Finished
+
+The key features of this idiomatic usage is that the majority of code is simply
+creating a module level logger with ``getLogger(__name__)``, and using that
+logger to do any needed logging. This is concise while allowing downstream code
+fine grained control if needed. Logged messages to the module-level logger get
+forwarded up to handlers of loggers in higher-level modules, all the way up to
+the root logger; for this reason this approach is known as hierarchical logging.
+
+For logging to be useful, it needs to be configured: setting the levels and
+destinations for each logger, potentially changing how specific modules log,
+often based on command-line arguments or application configuration. In most
+cases, like the one above, only the root logger needs to be so configured, since
+all the lower level loggers at module level eventually forward their messages to
+its handlers. :func:`~logging.basicConfig` provides a quick way to configure
+the root logger that handles many use cases.
The module provides a lot of functionality and flexibility. If you are
unfamiliar with logging, the best way to get to grips with it is to view the
@@ -1151,89 +1191,31 @@ functions.
.. function:: debug(msg, *args, **kwargs)
- Logs a message with level :const:`DEBUG` on the root logger. The *msg* is the
- message format string, and the *args* are the arguments which are merged into
- *msg* using the string formatting operator. (Note that this means that you can
- use keywords in the format string, together with a single dictionary argument.)
-
- There are three keyword arguments in *kwargs* which are inspected: *exc_info*
- which, if it does not evaluate as false, causes exception information to be
- added to the logging message. If an exception tuple (in the format returned by
- :func:`sys.exc_info`) or an exception instance is provided, it is used;
- otherwise, :func:`sys.exc_info` is called to get the exception information.
-
- The second optional keyword argument is *stack_info*, which defaults to
- ``False``. If true, stack information is added to the logging
- message, including the actual logging call. Note that this is not the same
- stack information as that displayed through specifying *exc_info*: The
- former is stack frames from the bottom of the stack up to the logging call
- in the current thread, whereas the latter is information about stack frames
- which have been unwound, following an exception, while searching for
- exception handlers.
-
- You can specify *stack_info* independently of *exc_info*, e.g. to just show
- how you got to a certain point in your code, even when no exceptions were
- raised. The stack frames are printed following a header line which says:
-
- .. code-block:: none
+ This is a convenience function that calls :meth:`Logger.debug`, on the root
+ logger. The handling of the arguments is in every way identical
+ to what is described in that method.
- Stack (most recent call last):
+ The only difference is that if the root logger has no handlers, then
+ :func:`basicConfig` is called, prior to calling ``debug`` on the root logger.
- This mimics the ``Traceback (most recent call last):`` which is used when
- displaying exception frames.
+ For very short scripts or quick demonstrations of ``logging`` facilities,
+ ``debug`` and the other module-level functions may be convenient. However,
+ most programs will want to carefully and explicitly control the logging
+ configuration, and should therefore prefer creating a module-level logger and
+ calling :meth:`Logger.debug` (or other level-specific methods) on it, as
+ described at the beginnning of this documentation.
- The third optional keyword argument is *extra* which can be used to pass a
- dictionary which is used to populate the __dict__ of the LogRecord created for
- the logging event with user-defined attributes. These custom attributes can then
- be used as you like. For example, they could be incorporated into logged
- messages. For example::
-
- FORMAT = '%(asctime)s %(clientip)-15s %(user)-8s %(message)s'
- logging.basicConfig(format=FORMAT)
- d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
- logging.warning('Protocol problem: %s', 'connection reset', extra=d)
-
- would print something like:
-
- .. code-block:: none
-
- 2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset
-
- The keys in the dictionary passed in *extra* should not clash with the keys used
- by the logging system. (See the :class:`Formatter` documentation for more
- information on which keys are used by the logging system.)
-
- If you choose to use these attributes in logged messages, you need to exercise
- some care. In the above example, for instance, the :class:`Formatter` has been
- set up with a format string which expects 'clientip' and 'user' in the attribute
- dictionary of the LogRecord. If these are missing, the message will not be
- logged because a string formatting exception will occur. So in this case, you
- always need to pass the *extra* dictionary with these keys.
-
- While this might be annoying, this feature is intended for use in specialized
- circumstances, such as multi-threaded servers where the same code executes in
- many contexts, and interesting conditions which arise are dependent on this
- context (such as remote client IP address and authenticated user name, in the
- above example). In such circumstances, it is likely that specialized
- :class:`Formatter`\ s would be used with particular :class:`Handler`\ s.
-
- This function (as well as :func:`info`, :func:`warning`, :func:`error` and
- :func:`critical`) will call :func:`basicConfig` if the root logger doesn't
- have any handler attached.
-
- .. versionchanged:: 3.2
- The *stack_info* parameter was added.
.. function:: info(msg, *args, **kwargs)
- Logs a message with level :const:`INFO` on the root logger. The arguments are
- interpreted as for :func:`debug`.
+ Logs a message with level :const:`INFO` on the root logger. The arguments and behavior
+ are otherwise the same as for :func:`debug`.
.. function:: warning(msg, *args, **kwargs)
- Logs a message with level :const:`WARNING` on the root logger. The arguments
- are interpreted as for :func:`debug`.
+ Logs a message with level :const:`WARNING` on the root logger. The arguments and behavior
+ are otherwise the same as for :func:`debug`.
.. note:: There is an obsolete function ``warn`` which is functionally
identical to ``warning``. As ``warn`` is deprecated, please do not use
@@ -1246,26 +1228,26 @@ functions.
.. function:: error(msg, *args, **kwargs)
- Logs a message with level :const:`ERROR` on the root logger. The arguments are
- interpreted as for :func:`debug`.
+ Logs a message with level :const:`ERROR` on the root logger. The arguments and behavior
+ are otherwise the same as for :func:`debug`.
.. function:: critical(msg, *args, **kwargs)
- Logs a message with level :const:`CRITICAL` on the root logger. The arguments
- are interpreted as for :func:`debug`.
+ Logs a message with level :const:`CRITICAL` on the root logger. The arguments and behavior
+ are otherwise the same as for :func:`debug`.
.. function:: exception(msg, *args, **kwargs)
- Logs a message with level :const:`ERROR` on the root logger. The arguments are
- interpreted as for :func:`debug`. Exception info is added to the logging
+ Logs a message with level :const:`ERROR` on the root logger. The arguments and behavior
+ are otherwise the same as for :func:`debug`. Exception info is added to the logging
message. This function should only be called from an exception handler.
.. function:: log(level, msg, *args, **kwargs)
- Logs a message with level *level* on the root logger. The other arguments are
- interpreted as for :func:`debug`.
+ Logs a message with level *level* on the root logger. The arguments and behavior
+ are otherwise the same as for :func:`debug`.
.. function:: disable(level=CRITICAL)