Skip to content

Commit 7f418fb

Browse files
quicknirvsajip
andauthored
gh-98731: Improvements to the logging documentation (GH-101618)
Co-authored-by: Vinay Sajip <[email protected]>
1 parent 8e2aab7 commit 7f418fb

File tree

2 files changed

+108
-162
lines changed

2 files changed

+108
-162
lines changed

Doc/howto/logging.rst

Lines changed: 41 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ or *severity*.
2525
When to use logging
2626
^^^^^^^^^^^^^^^^^^^
2727

28-
Logging provides a set of convenience functions for simple logging usage. These
29-
are :func:`debug`, :func:`info`, :func:`warning`, :func:`error` and
30-
:func:`critical`. To determine when to use logging, see the table below, which
31-
states, for each of a set of common tasks, the best tool to use for it.
28+
You can access logging functionality by creating a logger via ``logger =
29+
getLogger(__name__)``, and then calling the logger's :meth:`~Logger.debug`,
30+
:meth:`~Logger.info`, :meth:`~Logger.warning`, :meth:`~Logger.error` and
31+
:meth:`~Logger.critical` methods. To determine when to use logging, and to see
32+
which logger methods to use when, see the table below. It states, for each of a
33+
set of common tasks, the best tool to use for that task.
3234

3335
+-------------------------------------+--------------------------------------+
3436
| Task you want to perform | The best tool for the task |
@@ -37,8 +39,8 @@ states, for each of a set of common tasks, the best tool to use for it.
3739
| usage of a command line script or | |
3840
| program | |
3941
+-------------------------------------+--------------------------------------+
40-
| Report events that occur during | :func:`logging.info` (or |
41-
| normal operation of a program (e.g. | :func:`logging.debug` for very |
42+
| Report events that occur during | A logger's :meth:`~Logger.info` (or |
43+
| normal operation of a program (e.g. | :meth:`~Logger.debug` method for very|
4244
| for status monitoring or fault | detailed output for diagnostic |
4345
| investigation) | purposes) |
4446
+-------------------------------------+--------------------------------------+
@@ -47,22 +49,23 @@ states, for each of a set of common tasks, the best tool to use for it.
4749
| | the client application should be |
4850
| | modified to eliminate the warning |
4951
| | |
50-
| | :func:`logging.warning` if there is |
51-
| | nothing the client application can do|
52-
| | about the situation, but the event |
53-
| | should still be noted |
52+
| | A logger's :meth:`~Logger.warning` |
53+
| | method if there is nothing the client|
54+
| | application can do about the |
55+
| | situation, but the event should still|
56+
| | be noted |
5457
+-------------------------------------+--------------------------------------+
5558
| Report an error regarding a | Raise an exception |
5659
| particular runtime event | |
5760
+-------------------------------------+--------------------------------------+
58-
| Report suppression of an error | :func:`logging.error`, |
59-
| without raising an exception (e.g. | :func:`logging.exception` or |
60-
| error handler in a long-running | :func:`logging.critical` as |
61+
| Report suppression of an error | A logger's :meth:`~Logger.error`, |
62+
| without raising an exception (e.g. | :meth:`~Logger.exception` or |
63+
| error handler in a long-running | :meth:`~Logger.critical` method as |
6164
| server process) | appropriate for the specific error |
6265
| | and application domain |
6366
+-------------------------------------+--------------------------------------+
6467

65-
The logging functions are named after the level or severity of the events
68+
The logger methods are named after the level or severity of the events
6669
they are used to track. The standard levels and their applicability are
6770
described below (in increasing order of severity):
6871

@@ -115,12 +118,18 @@ If you type these lines into a script and run it, you'll see:
115118
WARNING:root:Watch out!
116119
117120
printed out on the console. The ``INFO`` message doesn't appear because the
118-
default level is ``WARNING``. The printed message includes the indication of
119-
the level and the description of the event provided in the logging call, i.e.
120-
'Watch out!'. Don't worry about the 'root' part for now: it will be explained
121-
later. The actual output can be formatted quite flexibly if you need that;
122-
formatting options will also be explained later.
123-
121+
default level is ``WARNING``. The printed message includes the indication of the
122+
level and the description of the event provided in the logging call, i.e.
123+
'Watch out!'. The actual output can be formatted quite flexibly if you need
124+
that; formatting options will also be explained later.
125+
126+
Notice that in this example, we use functions directly on the ``logging``
127+
module, like ``logging.debug``, rather than creating a logger and calling
128+
functions on it. These functions operation on the root logger, but can be useful
129+
as they will call :func:`~logging.basicConfig` for you if it has not been called yet, like in
130+
this example. In larger programs you'll usually want to control the logging
131+
configuration explicitly however - so for that reason as well as others, it's
132+
better to create loggers and call their methods.
124133

125134
Logging to a file
126135
^^^^^^^^^^^^^^^^^
@@ -130,11 +139,12 @@ look at that next. Be sure to try the following in a newly started Python
130139
interpreter, and don't just continue from the session described above::
131140

132141
import logging
142+
logger = logging.getLogger(__name__)
133143
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)
134-
logging.debug('This message should go to the log file')
135-
logging.info('So should this')
136-
logging.warning('And this, too')
137-
logging.error('And non-ASCII stuff, too, like Øresund and Malmö')
144+
logger.debug('This message should go to the log file')
145+
logger.info('So should this')
146+
logger.warning('And this, too')
147+
logger.error('And non-ASCII stuff, too, like Øresund and Malmö')
138148

139149
.. versionchanged:: 3.9
140150
The *encoding* argument was added. In earlier Python versions, or if not
@@ -148,10 +158,10 @@ messages:
148158

149159
.. code-block:: none
150160
151-
DEBUG:root:This message should go to the log file
152-
INFO:root:So should this
153-
WARNING:root:And this, too
154-
ERROR:root:And non-ASCII stuff, too, like Øresund and Malmö
161+
DEBUG:__main__:This message should go to the log file
162+
INFO:__main__:So should this
163+
WARNING:__main__:And this, too
164+
ERROR:__main__:And non-ASCII stuff, too, like Øresund and Malmö
155165
156166
This example also shows how you can set the logging level which acts as the
157167
threshold for tracking. In this case, because we set the threshold to
@@ -180,11 +190,9 @@ following example::
180190
raise ValueError('Invalid log level: %s' % loglevel)
181191
logging.basicConfig(level=numeric_level, ...)
182192

183-
The call to :func:`basicConfig` should come *before* any calls to
184-
:func:`debug`, :func:`info`, etc. Otherwise, those functions will call
185-
:func:`basicConfig` for you with the default options. As it's intended as a
186-
one-off simple configuration facility, only the first call will actually do
187-
anything: subsequent calls are effectively no-ops.
193+
The call to :func:`basicConfig` should come *before* any calls to a logger's
194+
methods such as :meth:`~Logger.debug`, :meth:`~Logger.info`, etc. Otherwise,
195+
that logging event may not be handled in the desired manner.
188196

189197
If you run the above script several times, the messages from successive runs
190198
are appended to the file *example.log*. If you want each run to start afresh,
@@ -197,50 +205,6 @@ The output will be the same as before, but the log file is no longer appended
197205
to, so the messages from earlier runs are lost.
198206

199207

200-
Logging from multiple modules
201-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
202-
203-
If your program consists of multiple modules, here's an example of how you
204-
could organize logging in it::
205-
206-
# myapp.py
207-
import logging
208-
import mylib
209-
210-
def main():
211-
logging.basicConfig(filename='myapp.log', level=logging.INFO)
212-
logging.info('Started')
213-
mylib.do_something()
214-
logging.info('Finished')
215-
216-
if __name__ == '__main__':
217-
main()
218-
219-
::
220-
221-
# mylib.py
222-
import logging
223-
224-
def do_something():
225-
logging.info('Doing something')
226-
227-
If you run *myapp.py*, you should see this in *myapp.log*:
228-
229-
.. code-block:: none
230-
231-
INFO:root:Started
232-
INFO:root:Doing something
233-
INFO:root:Finished
234-
235-
which is hopefully what you were expecting to see. You can generalize this to
236-
multiple modules, using the pattern in *mylib.py*. Note that for this simple
237-
usage pattern, you won't know, by looking in the log file, *where* in your
238-
application your messages came from, apart from looking at the event
239-
description. If you want to track the location of your messages, you'll need
240-
to refer to the documentation beyond the tutorial level -- see
241-
:ref:`logging-advanced-tutorial`.
242-
243-
244208
Logging variable data
245209
^^^^^^^^^^^^^^^^^^^^^
246210

Doc/library/logging.rst

Lines changed: 67 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,53 @@ is that all Python modules can participate in logging, so your application log
3030
can include your own messages integrated with messages from third-party
3131
modules.
3232

33-
The simplest example:
33+
Here's a simple example of idiomatic usage: ::
34+
35+
# myapp.py
36+
import logging
37+
import mylib
38+
logger = logging.getLogger(__name__)
39+
40+
def main():
41+
logging.basicConfig(filename='myapp.log', level=logging.INFO)
42+
logger.info('Started')
43+
mylib.do_something()
44+
logger.info('Finished')
45+
46+
if __name__ == '__main__':
47+
main()
48+
49+
::
50+
51+
# mylib.py
52+
import logging
53+
logger = logging.getLogger(__name__)
54+
55+
def do_something():
56+
logger.info('Doing something')
57+
58+
If you run *myapp.py*, you should see this in *myapp.log*:
3459

3560
.. code-block:: none
3661
37-
>>> import logging
38-
>>> logging.warning('Watch out!')
39-
WARNING:root:Watch out!
62+
INFO:__main__:Started
63+
INFO:mylib:Doing something
64+
INFO:__main__:Finished
65+
66+
The key features of this idiomatic usage is that the majority of code is simply
67+
creating a module level logger with ``getLogger(__name__)``, and using that
68+
logger to do any needed logging. This is concise while allowing downstream code
69+
fine grained control if needed. Logged messages to the module-level logger get
70+
forwarded up to handlers of loggers in higher-level modules, all the way up to
71+
the root logger; for this reason this approach is known as hierarchical logging.
72+
73+
For logging to be useful, it needs to be configured: setting the levels and
74+
destinations for each logger, potentially changing how specific modules log,
75+
often based on command-line arguments or application configuration. In most
76+
cases, like the one above, only the root logger needs to be so configured, since
77+
all the lower level loggers at module level eventually forward their messages to
78+
its handlers. :func:`~logging.basicConfig` provides a quick way to configure
79+
the root logger that handles many use cases.
4080

4181
The module provides a lot of functionality and flexibility. If you are
4282
unfamiliar with logging, the best way to get to grips with it is to view the
@@ -1151,89 +1191,31 @@ functions.
11511191

11521192
.. function:: debug(msg, *args, **kwargs)
11531193

1154-
Logs a message with level :const:`DEBUG` on the root logger. The *msg* is the
1155-
message format string, and the *args* are the arguments which are merged into
1156-
*msg* using the string formatting operator. (Note that this means that you can
1157-
use keywords in the format string, together with a single dictionary argument.)
1158-
1159-
There are three keyword arguments in *kwargs* which are inspected: *exc_info*
1160-
which, if it does not evaluate as false, causes exception information to be
1161-
added to the logging message. If an exception tuple (in the format returned by
1162-
:func:`sys.exc_info`) or an exception instance is provided, it is used;
1163-
otherwise, :func:`sys.exc_info` is called to get the exception information.
1164-
1165-
The second optional keyword argument is *stack_info*, which defaults to
1166-
``False``. If true, stack information is added to the logging
1167-
message, including the actual logging call. Note that this is not the same
1168-
stack information as that displayed through specifying *exc_info*: The
1169-
former is stack frames from the bottom of the stack up to the logging call
1170-
in the current thread, whereas the latter is information about stack frames
1171-
which have been unwound, following an exception, while searching for
1172-
exception handlers.
1173-
1174-
You can specify *stack_info* independently of *exc_info*, e.g. to just show
1175-
how you got to a certain point in your code, even when no exceptions were
1176-
raised. The stack frames are printed following a header line which says:
1177-
1178-
.. code-block:: none
1194+
This is a convenience function that calls :meth:`Logger.debug`, on the root
1195+
logger. The handling of the arguments is in every way identical
1196+
to what is described in that method.
11791197

1180-
Stack (most recent call last):
1198+
The only difference is that if the root logger has no handlers, then
1199+
:func:`basicConfig` is called, prior to calling ``debug`` on the root logger.
11811200

1182-
This mimics the ``Traceback (most recent call last):`` which is used when
1183-
displaying exception frames.
1201+
For very short scripts or quick demonstrations of ``logging`` facilities,
1202+
``debug`` and the other module-level functions may be convenient. However,
1203+
most programs will want to carefully and explicitly control the logging
1204+
configuration, and should therefore prefer creating a module-level logger and
1205+
calling :meth:`Logger.debug` (or other level-specific methods) on it, as
1206+
described at the beginnning of this documentation.
11841207

1185-
The third optional keyword argument is *extra* which can be used to pass a
1186-
dictionary which is used to populate the __dict__ of the LogRecord created for
1187-
the logging event with user-defined attributes. These custom attributes can then
1188-
be used as you like. For example, they could be incorporated into logged
1189-
messages. For example::
1190-
1191-
FORMAT = '%(asctime)s %(clientip)-15s %(user)-8s %(message)s'
1192-
logging.basicConfig(format=FORMAT)
1193-
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
1194-
logging.warning('Protocol problem: %s', 'connection reset', extra=d)
1195-
1196-
would print something like:
1197-
1198-
.. code-block:: none
1199-
1200-
2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset
1201-
1202-
The keys in the dictionary passed in *extra* should not clash with the keys used
1203-
by the logging system. (See the :class:`Formatter` documentation for more
1204-
information on which keys are used by the logging system.)
1205-
1206-
If you choose to use these attributes in logged messages, you need to exercise
1207-
some care. In the above example, for instance, the :class:`Formatter` has been
1208-
set up with a format string which expects 'clientip' and 'user' in the attribute
1209-
dictionary of the LogRecord. If these are missing, the message will not be
1210-
logged because a string formatting exception will occur. So in this case, you
1211-
always need to pass the *extra* dictionary with these keys.
1212-
1213-
While this might be annoying, this feature is intended for use in specialized
1214-
circumstances, such as multi-threaded servers where the same code executes in
1215-
many contexts, and interesting conditions which arise are dependent on this
1216-
context (such as remote client IP address and authenticated user name, in the
1217-
above example). In such circumstances, it is likely that specialized
1218-
:class:`Formatter`\ s would be used with particular :class:`Handler`\ s.
1219-
1220-
This function (as well as :func:`info`, :func:`warning`, :func:`error` and
1221-
:func:`critical`) will call :func:`basicConfig` if the root logger doesn't
1222-
have any handler attached.
1223-
1224-
.. versionchanged:: 3.2
1225-
The *stack_info* parameter was added.
12261208

12271209
.. function:: info(msg, *args, **kwargs)
12281210

1229-
Logs a message with level :const:`INFO` on the root logger. The arguments are
1230-
interpreted as for :func:`debug`.
1211+
Logs a message with level :const:`INFO` on the root logger. The arguments and behavior
1212+
are otherwise the same as for :func:`debug`.
12311213

12321214

12331215
.. function:: warning(msg, *args, **kwargs)
12341216

1235-
Logs a message with level :const:`WARNING` on the root logger. The arguments
1236-
are interpreted as for :func:`debug`.
1217+
Logs a message with level :const:`WARNING` on the root logger. The arguments and behavior
1218+
are otherwise the same as for :func:`debug`.
12371219

12381220
.. note:: There is an obsolete function ``warn`` which is functionally
12391221
identical to ``warning``. As ``warn`` is deprecated, please do not use
@@ -1246,26 +1228,26 @@ functions.
12461228

12471229
.. function:: error(msg, *args, **kwargs)
12481230

1249-
Logs a message with level :const:`ERROR` on the root logger. The arguments are
1250-
interpreted as for :func:`debug`.
1231+
Logs a message with level :const:`ERROR` on the root logger. The arguments and behavior
1232+
are otherwise the same as for :func:`debug`.
12511233

12521234

12531235
.. function:: critical(msg, *args, **kwargs)
12541236

1255-
Logs a message with level :const:`CRITICAL` on the root logger. The arguments
1256-
are interpreted as for :func:`debug`.
1237+
Logs a message with level :const:`CRITICAL` on the root logger. The arguments and behavior
1238+
are otherwise the same as for :func:`debug`.
12571239

12581240

12591241
.. function:: exception(msg, *args, **kwargs)
12601242

1261-
Logs a message with level :const:`ERROR` on the root logger. The arguments are
1262-
interpreted as for :func:`debug`. Exception info is added to the logging
1243+
Logs a message with level :const:`ERROR` on the root logger. The arguments and behavior
1244+
are otherwise the same as for :func:`debug`. Exception info is added to the logging
12631245
message. This function should only be called from an exception handler.
12641246

12651247
.. function:: log(level, msg, *args, **kwargs)
12661248

1267-
Logs a message with level *level* on the root logger. The other arguments are
1268-
interpreted as for :func:`debug`.
1249+
Logs a message with level *level* on the root logger. The arguments and behavior
1250+
are otherwise the same as for :func:`debug`.
12691251

12701252
.. function:: disable(level=CRITICAL)
12711253

0 commit comments

Comments
 (0)