• Home
  • Raw
  • Download

Lines Matching +full:formatting +full:- +full:error +full:- +full:messages

1 .. _logging-cookbook:
7 :Author: Vinay Sajip <vinay_sajip at red-dove dot com>
11 :ref:`cookbook-ref-links`.
16 ---------------------------------
32 # create file handler which logs even debug messages
37 ch.setLevel(logging.ERROR)
39 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
78 .. code-block:: none
80 2005-03-23 23:47:11,663 - spam_application - INFO -
82 2005-03-23 23:47:11,665 - spam_application.auxiliary.Auxiliary - INFO -
84 2005-03-23 23:47:11,665 - spam_application - INFO -
86 2005-03-23 23:47:11,668 - spam_application - INFO -
88 2005-03-23 23:47:11,668 - spam_application.auxiliary.Auxiliary - INFO -
90 2005-03-23 23:47:11,669 - spam_application.auxiliary.Auxiliary - INFO -
92 2005-03-23 23:47:11,670 - spam_application - INFO -
94 2005-03-23 23:47:11,671 - spam_application - INFO -
96 2005-03-23 23:47:11,672 - spam_application.auxiliary - INFO -
98 2005-03-23 23:47:11,673 - spam_application - INFO -
102 -----------------------------
135 .. code-block:: none
137 0 Thread-1 Hi from myfunc
139 505 Thread-1 Hi from myfunc
141 1007 Thread-1 Hi from myfunc
143 1508 Thread-1 Hi from myfunc
144 2010 Thread-1 Hi from myfunc
146 2512 Thread-1 Hi from myfunc
148 3013 Thread-1 Hi from myfunc
149 3515 Thread-1 Hi from myfunc
151 4017 Thread-1 Hi from myfunc
153 4518 Thread-1 Hi from myfunc
159 --------------------------------
163 will be beneficial for an application to log all messages of all severities to a
167 previous simple module-based configuration example::
173 # create file handler which logs even debug messages
178 ch.setLevel(logging.ERROR)
180 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
191 logger.error('error message')
197 The ability to create new handlers with higher- or lower-severity filters can be
205 .. _multiple-destinations:
208 --------------------------------
211 in differing circumstances. Say you want to log messages with levels of DEBUG
212 and higher to file, and those messages at level INFO and higher to the console.
214 messages should not. Here's how you can achieve this::
218 # set up logging to file - see previous section for more details
220 format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
221 datefmt='%m-%d %H:%M',
224 # define a Handler which writes INFO messages or higher to the sys.stderr
228 formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
246 logger2.error('The five boxing wizards jump quickly.')
250 .. code-block:: none
255 myapp.area2 : ERROR The five boxing wizards jump quickly.
259 .. code-block:: none
261 10-22 22:19 root INFO Jackdaws love my big sphinx of quartz.
262 10-22 22:19 myapp.area1 DEBUG Quick zephyrs blow, vexing daft Jim.
263 10-22 22:19 myapp.area1 INFO How quickly daft jumping zebras vex.
264 10-22 22:19 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack.
265 10-22 22:19 myapp.area2 ERROR The five boxing wizards jump quickly.
267 As you can see, the DEBUG message only shows up in the file. The other messages
275 choose a different directory name for the log - just ensure that the directory exists
279 .. _custom-level-handling:
282 -------------------------
289 * Send messages of severity ``INFO`` and ``WARNING`` to ``sys.stdout``
290 * Send messages of severity ``ERROR`` and above to ``sys.stderr``
291 * Send messages of severity ``DEBUG`` and above to file ``app.log``
295 .. code-block:: json
302 "format": "%(levelname)-8s - %(message)s"
314 "level": "ERROR",
335 This configuration does *almost* what we want, except that ``sys.stdout`` would show messages
336 of severity ``ERROR`` and only events of this severity and higher will be tracked
337 as well as ``INFO`` and ``WARNING`` messages. To prevent this, we can set up a filter which
338 excludes those messages and add it to the relevant handler. This can be configured by
341 .. code-block:: json
354 .. code-block:: json
369 .. code-block:: python
383 so its module will be ``__main__`` - hence the ``__main__.filter_maker`` in the
389 .. code-block:: python
401 "format": "%(levelname)-8s - %(message)s"
420 "level": "ERROR",
454 logging.error('An ERROR message')
459 .. code-block:: shell
465 .. code-block:: shell
471 DEBUG - A DEBUG message
472 INFO - An INFO message
473 WARNING - A WARNING message
474 ERROR - An ERROR message
475 CRITICAL - A CRITICAL message
479 ERROR - An ERROR message
480 CRITICAL - A CRITICAL message
484 INFO - An INFO message
485 WARNING - A WARNING message
489 ----------------------------
514 logger.error('error message')
523 properly preceded with the binary-encoded length, as the new logging
544 .. _blocking-handlers:
547 --------------------------------
558 performing mail or network infrastructure). But almost any network-based
563 One solution is to use a two-part approach. For the first part, attach only a
565 performance-critical threads. They simply write to their queue, which can be
569 in your code. If you are a library developer who has performance-critical
584 resource-friendly than, say, having threaded versions of the existing handler
589 que = queue.Queue(-1) # no limit on size
607 .. code-block:: none
629 .. _network-logging:
632 -----------------------------------------------------
660 logger2.error('The five boxing wizards jump quickly.')
681 Handle multiple requests - each expected to be a 4-byte length,
692 chunk = chunk + self.connection.recv(slen - len(chunk))
709 # is normally called AFTER logger-level filtering. If you want
716 Simple TCP socket-based logging receiver suitable for testing.
742 format='%(relativeCreated)5d %(name)-15s %(levelname)-8s %(message)s')
753 .. code-block:: none
760 69 myapp.area2 ERROR The five boxing wizards jump quickly.
772 .. _socket-listener-gist: https://gist.github.com/vsajip/4b227eeec43817465ca835ca66f75e2b
775 process-management tool such as `Supervisor <http://supervisord.org/>`_.
776 `Here is a Gist <socket-listener-gist_>`__
777 which provides the bare-bones files to run the above functionality using
780 +-------------------------+----------------------------------------------------+
785 +-------------------------+----------------------------------------------------+
787 | | entries for the listener and a multi-process web |
789 +-------------------------+----------------------------------------------------+
792 +-------------------------+----------------------------------------------------+
795 +-------------------------+----------------------------------------------------+
798 +-------------------------+----------------------------------------------------+
800 +-------------------------+----------------------------------------------------+
802 +-------------------------+----------------------------------------------------+
807 without conflicting with one another --- they all go through the socket listener.
811 #. Download `the Gist <socket-listener-gist_>`__
817 This creates a :file:`run` subdirectory to contain Supervisor-related and
830 worker processes in a non-deterministic way.
833 ``venv/bin/supervisorctl -c supervisor.conf shutdown``.
840 .. _context-info:
843 ----------------------------------------------------
847 networked application, it may be desirable to log client-specific information
851 :class:`Logger` instances on a per-connection basis, this is not a good idea
865 :meth:`debug`, :meth:`info`, :meth:`warning`, :meth:`error`,
871 :class:`Logger` instance and a dict-like object which contains your contextual
891 an 'extra' key in the keyword argument whose value is the dict-like object
895 The advantage of using 'extra' is that the values in the dict-like object are
898 the keys of the dict-like object. If you need a different method, e.g. if you
905 This example adapter expects the passed in dict-like object to have a
917 ``some_conn_id`` prepended to the log messages.
922 You don't need to pass an actual dict to a :class:`LoggerAdapter` - you could
928 .. _filters-contextual:
933 You can also add contextual information to log output using a user-defined
941 add, say, information from the request - say, the remote IP address and remote
942 user's username - to the ``LogRecord``, using the attribute names 'ip' and
968 levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
970 … format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
986 .. code-block:: none
988 2010-09-06 22:38:15,292 a.b.c DEBUG IP: 123.231.231.123 User: fred A debug message
989 …2010-09-06 22:38:15,300 a.b.c INFO IP: 192.168.0.1 User: sheila An info message with som…
990 …2010-09-06 22:38:15,300 d.e.f CRITICAL IP: 127.0.0.1 User: sheila A message at CRITICAL le…
991 …2010-09-06 22:38:15,300 d.e.f ERROR IP: 127.0.0.1 User: jim A message at ERROR level…
992 …2010-09-06 22:38:15,300 d.e.f DEBUG IP: 127.0.0.1 User: sheila A message at DEBUG level…
993 …2010-09-06 22:38:15,300 d.e.f ERROR IP: 123.231.231.123 User: fred A message at ERROR level…
994 …2010-09-06 22:38:15,300 d.e.f CRITICAL IP: 192.168.0.1 User: jim A message at CRITICAL le…
995 …2010-09-06 22:38:15,300 d.e.f CRITICAL IP: 127.0.0.1 User: sheila A message at CRITICAL le…
996 …2010-09-06 22:38:15,300 d.e.f DEBUG IP: 192.168.0.1 User: jim A message at DEBUG level…
997 …2010-09-06 22:38:15,301 d.e.f ERROR IP: 127.0.0.1 User: sheila A message at ERROR level…
998 …2010-09-06 22:38:15,301 d.e.f DEBUG IP: 123.231.231.123 User: fred A message at DEBUG level…
999 …2010-09-06 22:38:15,301 d.e.f INFO IP: 123.231.231.123 User: fred A message at INFO level …
1002 ----------------------
1004 Since Python 3.7, the :mod:`contextvars` module has provided context-local storage
1006 of storage may thus be generally preferable to thread-locals. The following example
1007 shows how, in a multi-threaded environment, logs can populated with contextual
1013 logging messages from the library (and other request processing code) are directed to
1019 .. code-block:: python
1034 ``Request`` and ``WebApp``. These simulate how real threaded web applications work -
1037 .. code-block:: python
1062 # A dummy set of requests which will be used in the simulation - we'll just pick
1079 …formatter = logging.Formatter('%(threadName)-11s %(appName)s %(name)-9s %(user)-6s %(ip)s %(method…
1089 A filter which injects context-specific information into logs and ensures
1106 webapp-specific log.
1140 aa('--count', '-c', type=int, default=100, help='How many requests to simulate')
1179 logged to :file:`app.log`. Each webapp-specific log will contain only log entries for
1184 .. code-block:: shell
1186 ~/logging-contextual-webapp$ python main.py
1189 ~/logging-contextual-webapp$ wc -l *.log
1194 ~/logging-contextual-webapp$ head -3 app1.log
1195 Thread-3 (process_request) app1 __main__ jim 192.168.3.21 POST Request processing started
1196 Thread-3 (process_request) app1 webapplib jim 192.168.3.21 POST Hello from webapplib!
1197 Thread-5 (process_request) app1 __main__ jim 192.168.3.21 POST Request processing started
1198 ~/logging-contextual-webapp$ head -3 app2.log
1199 Thread-1 (process_request) app2 __main__ sheila 192.168.2.21 GET Request processing started
1200 Thread-1 (process_request) app2 webapplib sheila 192.168.2.21 GET Hello from webapplib!
1201 Thread-2 (process_request) app2 __main__ jim 192.168.2.20 GET Request processing started
1202 ~/logging-contextual-webapp$ head app.log
1203 Thread-1 (process_request) app2 __main__ sheila 192.168.2.21 GET Request processing started
1204 Thread-1 (process_request) app2 webapplib sheila 192.168.2.21 GET Hello from webapplib!
1205 Thread-2 (process_request) app2 __main__ jim 192.168.2.20 GET Request processing started
1206 Thread-3 (process_request) app1 __main__ jim 192.168.3.21 POST Request processing started
1207 Thread-2 (process_request) app2 webapplib jim 192.168.2.20 GET Hello from webapplib!
1208 Thread-3 (process_request) app1 webapplib jim 192.168.3.21 POST Hello from webapplib!
1209 Thread-4 (process_request) app2 __main__ fred 192.168.2.22 GET Request processing started
1210 Thread-5 (process_request) app1 __main__ jim 192.168.3.21 POST Request processing started
1211 Thread-4 (process_request) app2 webapplib fred 192.168.2.22 GET Hello from webapplib!
1212 Thread-6 (process_request) app1 __main__ jim 192.168.3.21 POST Request processing started
1213 ~/logging-contextual-webapp$ grep app1 app1.log | wc -l
1215 ~/logging-contextual-webapp$ grep app2 app2.log | wc -l
1217 ~/logging-contextual-webapp$ grep app1 app.log | wc -l
1219 ~/logging-contextual-webapp$ grep app2 app.log | wc -l
1224 --------------------------------------------
1229 a new :class:`~LogRecord` instead of modifying it in-place, as shown in the following script::
1243 formatter = logging.Formatter('%(message)s from %(user)-8s')
1250 .. _multiple-processes:
1253 ------------------------------------------------
1255 Although logging is thread-safe, and logging to a single file from multiple
1264 :ref:`This section <network-logging>` documents this approach in more detail and
1276 all logging events to one of the processes in your multi-process application.
1281 thread rather than a separate listener process -- the implementation would be
1310 f = logging.Formatter('%(asctime)s %(processName)-10s %(name)s %(levelname)-8s %(message)s')
1314 # This is the listener process top-level loop: wait for logging events
1325 logger.handle(record) # No level or filter logic applied - just do it!
1334 logging.ERROR, logging.CRITICAL]
1338 MESSAGES = [
1351 # send all messages, for demo; no other level or filter logic applied.
1354 # This is the worker process top-level loop, which just logs ten events with
1356 # The print messages are just so you know it's doing something!
1365 message = choice(MESSAGES)
1373 queue = multiprocessing.Queue(-1)
1416 levels = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
1432 … 'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s'
1448 'filename': 'mplog-foo.log',
1454 'filename': 'mplog-errors.log',
1456 'level': 'ERROR',
1487 - e.g. the ``foo`` logger has a special handler which stores all events in the
1488 ``foo`` subsystem in a file ``mplog-foo.log``. This will be used by the logging
1490 the worker processes) to direct the messages to the appropriate destinations.
1499 .. code-block:: python
1501 queue = multiprocessing.Queue(-1)
1505 .. code-block:: python
1507 queue = multiprocessing.Manager().Queue(-1) # also works with the examples above
1530 <https://uwsgi-docs.readthedocs.io/en/latest/>`_ (or similar), multiple worker
1532 file-based handlers directly in your web application. Instead, use a
1534 process. This can be set up using a process management tool such as Supervisor - see
1539 -------------------
1566 # Log some messages
1579 .. code-block:: none
1598 .. _format-styles:
1600 Use of alternative formatting styles
1601 ------------------------------------
1604 formatting messages with variable content was to use the %-formatting
1605 method. Since then, Python has gained two new formatting approaches:
1610 formatting styles. The :class:`Formatter` class been enhanced to take an
1613 to the other two formatting styles. Backwards compatibility is maintained by
1619 .. code-block:: pycon
1631 2010-10-28 15:11:55,341 foo.bar DEBUG This is a DEBUG message
1633 2010-10-28 15:12:11,526 foo.bar CRITICAL This is a CRITICAL message
1638 2010-10-28 15:13:06,924 foo.bar DEBUG This is a DEBUG message
1640 2010-10-28 15:13:11,494 foo.bar CRITICAL This is a CRITICAL message
1643 Note that the formatting of logging messages for final output to logs is
1645 That can still use %-formatting, as shown here::
1647 >>> logger.error('This is an%s %s %s', 'other,', 'ERROR,', 'message')
1648 2010-10-28 15:19:29,833 foo.bar ERROR This is another, ERROR, message
1659 uses %-formatting to merge the format string and the variable arguments.
1661 all logging calls which are out there in existing code will be using %-format
1664 There is, however, a way that you can use {}- and $- formatting to construct
1665 your individual log messages. Recall that for a message you can use an
1688 Either of these can be used in place of a format string, to allow {}- or
1689 $-formatting to be used to build the actual "message" part which appears in the
1693 underscore --- not to be confused with _, the single underscore used as a
1700 .. code-block:: pycon
1718 While the above examples use ``print()`` to show how the formatting works, you
1723 approach: the actual formatting happens not when you make the logging call, but
1765 .. _custom-logrecord:
1768 -------------------------
1811 top-level logger, but this would not be invoked if an application developer
1812 attached a handler to a lower-level library logger --- so output from that
1838 However, it should be borne in mind that each link in the chain adds run-time
1844 .. _zeromq-handlers:
1846 Subclassing QueueHandler and QueueListener- a ZeroMQ example
1847 ------------------------------------------------------------
1852 You can use a :class:`QueueHandler` subclass to send messages to other kinds
1891 You can also subclass :class:`QueueListener` to get messages from other kinds
1906 .. _pynng-handlers:
1908 Subclassing QueueHandler and QueueListener- a ``pynng`` example
1909 ---------------------------------------------------------------
1914 The following snippets illustrate -- you can test them in an environment which has
1921 .. code-block:: python
1956 except pynng.Closed: # sometimes happens when you hit Ctrl-C
1961 event = json.loads(data.decode('utf-8'))
1972 print('Press Ctrl-C to stop.')
1987 .. code-block:: python
2007 # Send the record as UTF-8 encoded JSON
2010 self.queue.send(data.encode('utf-8'))
2020 format='%(levelname)-8s %(name)10s %(process)6s %(message)s')
2021 levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
2038 .. code-block:: console
2053 .. code-block:: console
2068 .. code-block:: console
2071 Press Ctrl-C to stop.
2094 An example dictionary-based configuration
2095 -----------------------------------------
2097 Below is an example of a logging configuration dictionary - it's taken from
2098 …he Django project <https://docs.djangoproject.com/en/stable/topics/logging/#configuring-logging>`_.
2127 'level': 'ERROR',
2139 'level': 'ERROR',
2151 section <https://docs.djangoproject.com/en/stable/topics/logging/#configuring-logging>`_
2154 .. _cookbook-rotator-namer:
2157 --------------------------------------------------------------
2192 .. code-block:: shell-session
2198 2023-01-20 02:28:17,767 Message no. 996
2199 2023-01-20 02:28:17,767 Message no. 997
2200 2023-01-20 02:28:17,767 Message no. 998
2203 ----------------------------------------
2220 Here's the script - the docstrings and the comments hopefully explain how it
2269 # would appear - hence the "if posix" clause.
2282 and logs a hundred messages with random levels to randomly selected
2290 levels = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
2300 # would appear - hence the "if posix" clause.
2326 # root logger, which allows all messages to be sent to the queue.
2356 … 'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s'
2360 'format': '%(name)-15s %(levelname)-8s %(processName)-10s %(message)s'
2377 'filename': 'mplog-foo.log',
2383 'filename': 'mplog-errors.log',
2386 'level': 'ERROR'
2431 Inserting a BOM into messages sent to a SysLogHandler
2432 -----------------------------------------------------
2436 following structure: an optional pure-ASCII component, followed by a UTF-8 Byte
2437 Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the
2438 :rfc:`relevant section of the specification <5424#section-6>`.)
2443 beginning of the message and hence not allowing any pure-ASCII component to
2448 want to produce :rfc:`5424`-compliant messages which include a BOM, an optional
2449 pure-ASCII sequence before it and arbitrary Unicode after it, encoded using
2450 UTF-8, then you need to do the following:
2458 The Unicode code point U+FEFF, when encoded using UTF-8, will be
2459 encoded as a UTF-8 BOM -- the byte-string ``b'\xef\xbb\xbf'``.
2463 way, it will remain unchanged after UTF-8 encoding).
2467 range, that's fine -- it will be encoded using UTF-8.
2469 The formatted message *will* be encoded using UTF-8 encoding by
2471 :rfc:`5424`-compliant messages. If you don't, logging may not complain, but your
2472 messages will not be RFC 5424-compliant, and your syslog daemon may complain.
2476 -------------------------------
2478 Although most logging messages are intended for reading by humans, and thus not
2479 readily machine-parseable, there might be circumstances where you want to output
2480 messages in a structured format which *is* capable of being parsed by a program
2484 which uses JSON to serialise the event in a machine-parseable manner::
2504 .. code-block:: none
2546 .. code-block:: none
2554 .. _custom-handlers:
2559 --------------------------------------------
2565 handlers in the stdlib don't offer built-in support. You can customize handler
2599 'encoding': 'utf-8',
2642 'encoding': 'utf-8',
2657 .. code-block:: shell-session
2661 2013-11-05 09:34:51,128 DEBUG mylogger A debug message
2662 $ ls -l chowntest.log
2663 -rw-r--r-- 1 pulse pulse 55 2013-11-05 09:34 chowntest.log
2667 supports :func:`dictConfig` - namely, Python 2.7, 3.2 or later. With pre-3.3
2671 In practice, the handler-creating function may be in a utility module somewhere
2686 types of file change - e.g. setting specific POSIX permission bits - in the
2690 :class:`~logging.FileHandler` - for example, one of the rotating file handlers,
2696 .. _formatting-styles:
2698 Using particular formatting styles throughout your application
2699 --------------------------------------------------------------
2703 the specification of ``{`` or ``$`` to support the formatting approaches
2705 governs the formatting of logging messages for final output to logs, and is
2715 because internally the logging package uses %-formatting to merge the format
2718 code will be using %-format strings.
2722 existing code could be using a given logger name and using %-formatting.
2724 For logging to work interoperably between any third-party libraries and your
2725 code, decisions about formatting need to be made at the level of the
2727 formatting styles can be accommodated.
2738 class implementation of this method is where the ``msg % args`` formatting
2739 happens, and where you can substitute your alternate formatting; however, you
2740 should be careful to support all formatting styles and allow %-formatting as
2751 There is another, perhaps simpler way that you can use {}- and $- formatting to
2752 construct your individual log messages. You may recall (from
2753 :ref:`arbitrary-object-messages`) that when logging you can use an arbitrary
2776 Either of these can be used in place of a format string, to allow {}- or
2777 $-formatting to be used to build the actual "message" part which appears in the
2784 Examples of this approach are given below. Firstly, formatting with
2798 Secondly, formatting with :class:`string.Template`::
2806 approach: the actual formatting happens not when you make the logging call, but
2814 .. _filters-dictconfig:
2819 -------------------------------------------
2872 logging.debug('hello - noshow')
2878 .. code-block:: none
2889 in :ref:`logging-config-dict-externalobj`. For example, you could have used
2894 handlers and formatters. See :ref:`logging-config-dict-userdef` for more
2895 information on how logging supports using user-defined objects in its
2896 configuration, and see the other cookbook recipe :ref:`custom-handlers` above.
2899 .. _custom-format-exception:
2901 Customized exception formatting
2902 -------------------------------
2904 There might be times when you want to do customized exception formatting - for
2947 .. code-block:: none
2950 …28/01/2015 07:21:23|ERROR|ZeroDivisionError: integer division or modulo by zero|'Traceback (most r…
2956 .. _spoken-messages:
2958 Speaking logging messages
2959 -------------------------
2961 There might be situations when it is desirable to have logging messages rendered
2963 text-to-speech (TTS) functionality available in your system, even if it doesn't have
2967 long time to complete, and that the frequency of logged messages will be not so
2968 high as to swamp the user with messages, and that it's acceptable to have the
2969 messages spoken one at a time rather than concurrently, The example implementation
2982 cmd = ['espeak', '-s150', '-ven+f3', msg]
3006 other systems altogether which can process messages via external programs run
3010 .. _buffered-logging:
3012 Buffering logging messages and outputting them conditionally
3013 ------------------------------------------------------------
3015 There might be situations where you want to log messages in a temporary area
3019 but if there is an error, you want all the debug information to be output as well
3020 as the error.
3026 - passed to another handler (the ``target`` handler) for processing. By default,
3035 parameter to ``foo`` which, if true, will log at ERROR and CRITICAL levels -
3044 writes to ``sys.stderr``, ``logging.ERROR`` and ``100`` respectively.
3059 flush_level = logging.ERROR
3090 write_line('about to log at ERROR ...')
3091 logger.error('Actually logged at ERROR')
3111 .. code-block:: none
3121 about to log at ERROR ...
3131 about to log at ERROR ...
3135 Actually logged at ERROR
3140 severity is ERROR or greater, but in that case, any previous events at lower
3150 .. _buffered-smtp:
3152 Sending logging messages to email, with buffering
3153 -------------------------------------------------
3155 To illustrate how you can send log messages via email, so that a set number of
3156 messages are sent per email, you can subclass
3160 send things via SMTP. (Run the downloaded script with the ``-h`` argument to see the
3163 .. code-block:: python
3182 self.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s"))
3207 aa('--port', '-p', type=int, default=587, help='SMTP port')
3212 aa('--subject', '-s',
3229 have ten log messages, and the eleventh will have two messages. That makes up 102
3230 messages as specified in the script.
3232 .. _utc-formatting:
3234 Formatting times using UTC (GMT) via configuration
3235 --------------------------------------------------
3291 .. code-block:: none
3293 2015-10-17 12:53:29,501 The local time is Sat Oct 17 13:53:29 2015
3294 2015-10-17 13:53:29,501 The local time is Sat Oct 17 13:53:29 2015
3300 .. _context-manager:
3303 ---------------------------------------------
3342 block exit - you could do this if you don't need the handler any more.
3358 logger.debug('5. This should appear twice - once on stderr and once on stdout.')
3374 .. code-block:: shell-session
3379 5. This should appear twice - once on stderr and once on stdout.
3380 5. This should appear twice - once on stderr and once on stdout.
3386 .. code-block:: shell-session
3389 5. This should appear twice - once on stderr and once on stdout.
3393 .. code-block:: shell-session
3398 5. This should appear twice - once on stderr and once on stdout.
3408 .. _starter-template:
3411 ----------------------------------
3415 * Use a logging level based on command-line arguments
3420 Suppose we have a command-line application whose job is to stop, start or
3425 command-line argument, defaulting to ``logging.INFO``. Here's one way that
3437 levels = ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
3438 parser.add_argument('--log-level', default='INFO', choices=levels)
3526 .. code-block:: shell-session
3543 .. code-block:: shell-session
3545 $ python app.py --log-level DEBUG start foo
3549 $ python app.py --log-level DEBUG stop foo bar
3553 $ python app.py --log-level DEBUG restart foo bar baz
3559 .. code-block:: shell-session
3561 $ python app.py --log-level WARNING start foo
3562 $ python app.py --log-level WARNING stop foo bar
3563 $ python app.py --log-level WARNING restart foo bar baz
3568 .. _qt-gui:
3571 --------------------
3575 cross-platform UI framework with Python bindings using :pypi:`PySide2`
3583 messages at random levels with random short delays in between).
3594 .. code-block:: python3
3637 # string is just a convenience - you could format a string for output any way
3655 # are named something like "Dummy-1". The function below gets the Qt name of the
3665 LEVELS = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
3678 # This example worker just outputs messages sequentially, interspersed with
3705 # * A read-only text edit window which holds formatted log messages
3716 logging.ERROR: 'red',
3738 fs = '%(asctime)s %(qThreadName)-12s %(levelname)-8s %(message)s'
3753 # Connect the non-worker slots and signals
3826 --------------------------------------
3847 tz_offset = re.compile(r'([+-]\d{2})(\d{2})$')
3871 hostname = '-'
3872 appname = self.appname or '-'
3874 msgid = '-'
3876 sdata = '-'
3879 # This should be a dict where the keys are SD-ID and the value is a
3880 # dict mapping PARAM-NAME to PARAM-VALUE (refer to the RFC for what these
3882 # There's no error checking here - it's purely for illustration, and you
3915 -------------------------------------------
3917 Sometimes, you need to interface to a third-party API which expects a file-like
3919 can do this using a class which wraps a logger with a file-like API.
3922 .. code-block:: python
3936 # doesn't actually do anything, but might be expected of a file-like
3937 # object - so optional depending on your situation
3941 # doesn't actually do anything, but might be expected of a file-like
3942 # object - so optional depending on your situation. You might want
3959 .. code-block:: text
3967 .. code-block:: python
3979 .. code-block:: pycon
3995 .. code-block:: python
4002 .. code-block:: text
4006 WARNING:demo: File "/home/runner/cookbook-loggerwriter/test.py", line 53, in <module>
4010 WARNING:demo: File "/home/runner/cookbook-loggerwriter/test.py", line 49, in main
4024 .. code-block:: python
4046 .. code-block:: text
4049 WARNING:demo: File "/home/runner/cookbook-loggerwriter/main.py", line 55, in <module>
4051 WARNING:demo: File "/home/runner/cookbook-loggerwriter/main.py", line 52, in main
4056 .. patterns-to-avoid:
4059 -----------------
4070 as this will lead to a "file is in use by another process" error. However, on
4075 a copy/paste/forget-to-change error).
4095 and wasted debugging time - log entries end up in unexpected places, or are
4097 and grows in size unexpectedly despite size-based rotation being supposedly
4100 Use the techniques outlined in :ref:`multiple-processes` to circumvent such
4128 the :ref:`existing mechanisms <context-info>` for passing contextual
4131 more fine-grained than that).
4133 .. _cookbook-ref-links:
4136 ---------------
4149 :ref:`Basic Tutorial <logging-basic-tutorial>`
4151 :ref:`Advanced Tutorial <logging-advanced-tutorial>`