mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
[3.12] [doc] Update logging documentation to improve grammar and elucidate an example. (GH-117541) (GH-117542)
(cherry picked from commit df912c913a
)
This commit is contained in:
parent
b5e12aa9ff
commit
663e7bc2ee
2 changed files with 72 additions and 11 deletions
|
@ -1915,7 +1915,7 @@ In a similar way to the above section, we can implement a listener and handler
|
||||||
using `pynng <https://pypi.org/project/pynng/>`_, which is a Python binding to
|
using `pynng <https://pypi.org/project/pynng/>`_, which is a Python binding to
|
||||||
`NNG <https://nng.nanomsg.org/>`_, billed as a spiritual successor to ZeroMQ.
|
`NNG <https://nng.nanomsg.org/>`_, billed as a spiritual successor to ZeroMQ.
|
||||||
The following snippets illustrate -- you can test them in an environment which has
|
The following snippets illustrate -- you can test them in an environment which has
|
||||||
``pynng`` installed. Juat for variety, we present the listener first.
|
``pynng`` installed. Just for variety, we present the listener first.
|
||||||
|
|
||||||
|
|
||||||
Subclass ``QueueListener``
|
Subclass ``QueueListener``
|
||||||
|
@ -1923,6 +1923,7 @@ Subclass ``QueueListener``
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
# listener.py
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
|
@ -1955,7 +1956,7 @@ Subclass ``QueueListener``
|
||||||
break
|
break
|
||||||
except pynng.Timeout:
|
except pynng.Timeout:
|
||||||
pass
|
pass
|
||||||
except pynng.Closed: # sometimes hit when you hit Ctrl-C
|
except pynng.Closed: # sometimes happens when you hit Ctrl-C
|
||||||
break
|
break
|
||||||
if data is None:
|
if data is None:
|
||||||
return None
|
return None
|
||||||
|
@ -1988,6 +1989,7 @@ Subclass ``QueueHandler``
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
# sender.py
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
|
@ -2015,9 +2017,10 @@ Subclass ``QueueHandler``
|
||||||
|
|
||||||
logging.getLogger('pynng').propagate = False
|
logging.getLogger('pynng').propagate = False
|
||||||
handler = NNGSocketHandler(DEFAULT_ADDR)
|
handler = NNGSocketHandler(DEFAULT_ADDR)
|
||||||
|
# Make sure the process ID is in the output
|
||||||
logging.basicConfig(level=logging.DEBUG,
|
logging.basicConfig(level=logging.DEBUG,
|
||||||
handlers=[logging.StreamHandler(), handler],
|
handlers=[logging.StreamHandler(), handler],
|
||||||
format='%(levelname)-8s %(name)10s %(message)s')
|
format='%(levelname)-8s %(name)10s %(process)6s %(message)s')
|
||||||
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
|
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
|
||||||
logging.CRITICAL)
|
logging.CRITICAL)
|
||||||
logger_names = ('myapp', 'myapp.lib1', 'myapp.lib2')
|
logger_names = ('myapp', 'myapp.lib1', 'myapp.lib2')
|
||||||
|
@ -2031,7 +2034,64 @@ Subclass ``QueueHandler``
|
||||||
delay = random.random() * 2 + 0.5
|
delay = random.random() * 2 + 0.5
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
|
|
||||||
You can run the above two snippets in separate command shells.
|
You can run the above two snippets in separate command shells. If we run the
|
||||||
|
listener in one shell and run the sender in two separate shells, we should see
|
||||||
|
something like the following. In the first sender shell:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ python sender.py
|
||||||
|
DEBUG myapp 613 Message no. 1
|
||||||
|
WARNING myapp.lib2 613 Message no. 2
|
||||||
|
CRITICAL myapp.lib2 613 Message no. 3
|
||||||
|
WARNING myapp.lib2 613 Message no. 4
|
||||||
|
CRITICAL myapp.lib1 613 Message no. 5
|
||||||
|
DEBUG myapp 613 Message no. 6
|
||||||
|
CRITICAL myapp.lib1 613 Message no. 7
|
||||||
|
INFO myapp.lib1 613 Message no. 8
|
||||||
|
(and so on)
|
||||||
|
|
||||||
|
In the second sender shell:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ python sender.py
|
||||||
|
INFO myapp.lib2 657 Message no. 1
|
||||||
|
CRITICAL myapp.lib2 657 Message no. 2
|
||||||
|
CRITICAL myapp 657 Message no. 3
|
||||||
|
CRITICAL myapp.lib1 657 Message no. 4
|
||||||
|
INFO myapp.lib1 657 Message no. 5
|
||||||
|
WARNING myapp.lib2 657 Message no. 6
|
||||||
|
CRITICAL myapp 657 Message no. 7
|
||||||
|
DEBUG myapp.lib1 657 Message no. 8
|
||||||
|
(and so on)
|
||||||
|
|
||||||
|
In the listener shell:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ python listener.py
|
||||||
|
Press Ctrl-C to stop.
|
||||||
|
DEBUG myapp 613 Message no. 1
|
||||||
|
WARNING myapp.lib2 613 Message no. 2
|
||||||
|
INFO myapp.lib2 657 Message no. 1
|
||||||
|
CRITICAL myapp.lib2 613 Message no. 3
|
||||||
|
CRITICAL myapp.lib2 657 Message no. 2
|
||||||
|
CRITICAL myapp 657 Message no. 3
|
||||||
|
WARNING myapp.lib2 613 Message no. 4
|
||||||
|
CRITICAL myapp.lib1 613 Message no. 5
|
||||||
|
CRITICAL myapp.lib1 657 Message no. 4
|
||||||
|
INFO myapp.lib1 657 Message no. 5
|
||||||
|
DEBUG myapp 613 Message no. 6
|
||||||
|
WARNING myapp.lib2 657 Message no. 6
|
||||||
|
CRITICAL myapp 657 Message no. 7
|
||||||
|
CRITICAL myapp.lib1 613 Message no. 7
|
||||||
|
INFO myapp.lib1 613 Message no. 8
|
||||||
|
DEBUG myapp.lib1 657 Message no. 8
|
||||||
|
(and so on)
|
||||||
|
|
||||||
|
As you can see, the logging from the two sender processes is interleaved in the
|
||||||
|
listener's output.
|
||||||
|
|
||||||
|
|
||||||
An example dictionary-based configuration
|
An example dictionary-based configuration
|
||||||
|
|
|
@ -63,12 +63,13 @@ If you run *myapp.py*, you should see this in *myapp.log*:
|
||||||
INFO:mylib:Doing something
|
INFO:mylib:Doing something
|
||||||
INFO:__main__:Finished
|
INFO:__main__:Finished
|
||||||
|
|
||||||
The key features of this idiomatic usage is that the majority of code is simply
|
The key feature of this idiomatic usage is that the majority of code is simply
|
||||||
creating a module level logger with ``getLogger(__name__)``, and using that
|
creating a module level logger with ``getLogger(__name__)``, and using that
|
||||||
logger to do any needed logging. This is concise while allowing downstream code
|
logger to do any needed logging. This is concise, while allowing downstream
|
||||||
fine grained control if needed. Logged messages to the module-level logger get
|
code fine-grained control if needed. Logged messages to the module-level logger
|
||||||
forwarded up to handlers of loggers in higher-level modules, all the way up to
|
get forwarded 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.
|
the highest-level logger known as the root logger; this approach is known as
|
||||||
|
hierarchical logging.
|
||||||
|
|
||||||
For logging to be useful, it needs to be configured: setting the levels and
|
For logging to be useful, it needs to be configured: setting the levels and
|
||||||
destinations for each logger, potentially changing how specific modules log,
|
destinations for each logger, potentially changing how specific modules log,
|
||||||
|
@ -82,8 +83,8 @@ 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
|
unfamiliar with logging, the best way to get to grips with it is to view the
|
||||||
tutorials (**see the links above and on the right**).
|
tutorials (**see the links above and on the right**).
|
||||||
|
|
||||||
The basic classes defined by the module, together with their functions, are
|
The basic classes defined by the module, together with their attributes and
|
||||||
listed below.
|
methods, are listed in the sections below.
|
||||||
|
|
||||||
* Loggers expose the interface that application code directly uses.
|
* Loggers expose the interface that application code directly uses.
|
||||||
* Handlers send the log records (created by loggers) to the appropriate
|
* Handlers send the log records (created by loggers) to the appropriate
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue