aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Doc/howto
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/howto')
-rw-r--r--Doc/howto/functional.rst2
-rw-r--r--Doc/howto/isolating-extensions.rst3
-rw-r--r--Doc/howto/logging-cookbook.rst62
3 files changed, 64 insertions, 3 deletions
diff --git a/Doc/howto/functional.rst b/Doc/howto/functional.rst
index 78e56e0c64f..053558e3890 100644
--- a/Doc/howto/functional.rst
+++ b/Doc/howto/functional.rst
@@ -1217,7 +1217,7 @@ flow inside a program. The book uses Scheme for its examples, but many of the
design approaches described in these chapters are applicable to functional-style
Python code.
-https://www.defmacro.org/ramblings/fp.html: A general introduction to functional
+https://defmacro.org/2006/06/19/fp.html: A general introduction to functional
programming that uses Java examples and has a lengthy historical introduction.
https://en.wikipedia.org/wiki/Functional_programming: General Wikipedia entry
diff --git a/Doc/howto/isolating-extensions.rst b/Doc/howto/isolating-extensions.rst
index fbc426ba1d7..7da6dc8a397 100644
--- a/Doc/howto/isolating-extensions.rst
+++ b/Doc/howto/isolating-extensions.rst
@@ -626,8 +626,7 @@ Open Issues
Several issues around per-module state and heap types are still open.
-Discussions about improving the situation are best held on the `capi-sig
-mailing list <https://mail.python.org/mailman3/lists/capi-sig.python.org/>`__.
+Discussions about improving the situation are best held on the `discuss forum under c-api tag <https://discuss.python.org/c/core-dev/c-api/30>`__.
Per-Class Scope
diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst
index 7d64a02358a..ae2697fbce3 100644
--- a/Doc/howto/logging-cookbook.rst
+++ b/Doc/howto/logging-cookbook.rst
@@ -4078,6 +4078,68 @@ lines. With this approach, you get better output:
WARNING:demo: 1/0
WARNING:demo:ZeroDivisionError: division by zero
+How to uniformly handle newlines in logging output
+--------------------------------------------------
+
+Usually, messages that are logged (say to console or file) consist of a single
+line of text. However, sometimes there is a need to handle messages with
+multiple lines - whether because a logging format string contains newlines, or
+logged data contains newlines. If you want to handle such messages uniformly, so
+that each line in the logged message appears uniformly formatted as if it was
+logged separately, you can do this using a handler mixin, as in the following
+snippet:
+
+.. code-block:: python
+
+ # Assume this is in a module mymixins.py
+ import copy
+
+ class MultilineMixin:
+ def emit(self, record):
+ s = record.getMessage()
+ if '\n' not in s:
+ super().emit(record)
+ else:
+ lines = s.splitlines()
+ rec = copy.copy(record)
+ rec.args = None
+ for line in lines:
+ rec.msg = line
+ super().emit(rec)
+
+You can use the mixin as in the following script:
+
+.. code-block:: python
+
+ import logging
+
+ from mymixins import MultilineMixin
+
+ logger = logging.getLogger(__name__)
+
+ class StreamHandler(MultilineMixin, logging.StreamHandler):
+ pass
+
+ if __name__ == '__main__':
+ logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-9s %(message)s',
+ handlers = [StreamHandler()])
+ logger.debug('Single line')
+ logger.debug('Multiple lines:\nfool me once ...')
+ logger.debug('Another single line')
+ logger.debug('Multiple lines:\n%s', 'fool me ...\ncan\'t get fooled again')
+
+The script, when run, prints something like:
+
+.. code-block:: text
+
+ 2025-07-02 13:54:47,234 DEBUG Single line
+ 2025-07-02 13:54:47,234 DEBUG Multiple lines:
+ 2025-07-02 13:54:47,234 DEBUG fool me once ...
+ 2025-07-02 13:54:47,234 DEBUG Another single line
+ 2025-07-02 13:54:47,234 DEBUG Multiple lines:
+ 2025-07-02 13:54:47,234 DEBUG fool me ...
+ 2025-07-02 13:54:47,234 DEBUG can't get fooled again
+
.. patterns-to-avoid: