@@ -268,12 +268,12 @@ Dealing with handlers that block
268268.. currentmodule :: logging.handlers
269269
270270Sometimes you have to get your logging handlers to do their work without
271- blocking the thread you’ re logging from. This is common in Web applications,
271+ blocking the thread you' re logging from. This is common in Web applications,
272272though of course it also occurs in other scenarios.
273273
274274A common culprit which demonstrates sluggish behaviour is the
275275:class: `SMTPHandler `: sending emails can take a long time, for a
276- number of reasons outside the developer’ s control (for example, a poorly
276+ number of reasons outside the developer' s control (for example, a poorly
277277performing mail or network infrastructure). But almost any network-based
278278handler can block: Even a :class: `SocketHandler ` operation may do a
279279DNS query under the hood which is too slow (and this query can be deep in the
@@ -292,7 +292,7 @@ developers who will use your code.
292292
293293The second part of the solution is :class: `QueueListener `, which has been
294294designed as the counterpart to :class: `QueueHandler `. A
295- :class: `QueueListener ` is very simple: it’ s passed a queue and some handlers,
295+ :class: `QueueListener ` is very simple: it' s passed a queue and some handlers,
296296and it fires up an internal thread which listens to its queue for LogRecords
297297sent from ``QueueHandlers `` (or any other source of ``LogRecords ``, for that
298298matter). The ``LogRecords `` are removed from the queue and passed to the
@@ -745,7 +745,7 @@ the basis for code meeting your own specific requirements::
745745 raise
746746 except:
747747 import sys, traceback
748- print >> sys.stderr, 'Whoops! Problem:'
748+ print( 'Whoops! Problem:', file=sys.stderr)
749749 traceback.print_exc(file=sys.stderr)
750750
751751 # Arrays used for random selections in this demo
@@ -964,6 +964,134 @@ and each time it reaches the size limit it is renamed with the suffix
964964Obviously this example sets the log length much too small as an extreme
965965example. You would want to set *maxBytes * to an appropriate value.
966966
967+ .. _format-styles :
968+
969+ Use of alternative formatting styles
970+ ------------------------------------
971+
972+ When logging was added to the Python standard library, the only way of
973+ formatting messages with variable content was to use the %-formatting
974+ method. Since then, Python has gained two new formatting approaches:
975+ string.Template (added in Python 2.4) and str.format (added in Python 2.6).
976+
977+ Logging now (as of 3.2) provides improved support for these two additional
978+ formatting styles. The :class: `Formatter ` class been enhanced for Python 3.2 to
979+ take an additional, optional keyword parameter named ``style ``. This defaults
980+ to ``'%' ``, but other possible values are ``'{' `` and ``'$' ``, which correspond
981+ to the other two formatting styles. Backwards compatibility is maintained by
982+ default (as you would expect), but by explicitly specifying a style parameter,
983+ you get the ability to specify format strings which work with
984+ :meth: `str.format ` or :class: `string.Template `. Here's an example console
985+ session to show the possibilities:
986+
987+ .. code-block :: pycon
988+
989+ >>> import logging
990+ >>> root = logging.getLogger()
991+ >>> root.setLevel(logging.DEBUG)
992+ >>> handler = logging.StreamHandler()
993+ >>> bf = logging.Formatter('{asctime} {name} {levelname:8s} {message}',
994+ ... style='{')
995+ >>> handler.setFormatter(bf)
996+ >>> root.addHandler(handler)
997+ >>> logger = logging.getLogger('foo.bar')
998+ >>> logger.debug('This is a DEBUG message')
999+ 2010-10-28 15:11:55,341 foo.bar DEBUG This is a DEBUG message
1000+ >>> logger.critical('This is a CRITICAL message')
1001+ 2010-10-28 15:12:11,526 foo.bar CRITICAL This is a CRITICAL message
1002+ >>> df = logging.Formatter('$asctime $name ${levelname} $message',
1003+ ... style='$')
1004+ >>> handler.setFormatter(df)
1005+ >>> logger.debug('This is a DEBUG message')
1006+ 2010-10-28 15:13:06,924 foo.bar DEBUG This is a DEBUG message
1007+ >>> logger.critical('This is a CRITICAL message')
1008+ 2010-10-28 15:13:11,494 foo.bar CRITICAL This is a CRITICAL message
1009+ >>>
1010+
1011+ Note that the formatting of logging messages for final output to logs is
1012+ completely independent of how an individual logging message is constructed.
1013+ That can still use %-formatting, as shown here::
1014+
1015+ >>> logger.error('This is an%s %s %s', 'other,', 'ERROR,', 'message')
1016+ 2010-10-28 15:19:29,833 foo.bar ERROR This is another, ERROR, message
1017+ >>>
1018+
1019+ Logging calls (``logger.debug() ``, ``logger.info() `` etc.) only take
1020+ positional parameters for the actual logging message itself, with keyword
1021+ parameters used only for determining options for how to handle the actual
1022+ logging call (e.g. the ``exc_info `` keyword parameter to indicate that
1023+ traceback information should be logged, or the ``extra `` keyword parameter
1024+ to indicate additional contextual information to be added to the log). So
1025+ you cannot directly make logging calls using :meth: `str.format ` or
1026+ :class: `string.Template ` syntax, because internally the logging package
1027+ uses %-formatting to merge the format string and the variable arguments.
1028+ There would no changing this while preserving backward compatibility, since
1029+ all logging calls which are out there in existing code will be using %-format
1030+ strings.
1031+
1032+ There is, however, a way that you can use {}- and $- formatting to construct
1033+ your individual log messages. Recall that for a message you can use an
1034+ arbitrary object as a message format string, and that the logging package will
1035+ call ``str() `` on that object to get the actual format string. Consider the
1036+ following two classes::
1037+
1038+ class BraceMessage(object):
1039+ def __init__(self, fmt, *args, **kwargs):
1040+ self.fmt = fmt
1041+ self.args = args
1042+ self.kwargs = kwargs
1043+
1044+ def __str__(self):
1045+ return self.fmt.format(*self.args, **self.kwargs)
1046+
1047+ class DollarMessage(object):
1048+ def __init__(self, fmt, **kwargs):
1049+ self.fmt = fmt
1050+ self.kwargs = kwargs
1051+
1052+ def __str__(self):
1053+ from string import Template
1054+ return Template(self.fmt).substitute(**self.kwargs)
1055+
1056+ Either of these can be used in place of a format string, to allow {}- or
1057+ $-formatting to be used to build the actual "message" part which appears in the
1058+ formatted log output in place of "%(message)s" or "{message}" or "$message".
1059+ It's a little unwieldy to use the class names whenever you want to log
1060+ something, but it's quite palatable if you use an alias such as __ (double
1061+ underscore – not to be confused with _, the single underscore used as a
1062+ synonym/alias for :func: `gettext.gettext ` or its brethren).
1063+
1064+ The above classes are not included in Python, though they're easy enough to
1065+ copy and paste into your own code. They can be used as follows (assuming that
1066+ they're declared in a module called ``wherever ``):
1067+
1068+ .. code-block :: pycon
1069+
1070+ >>> from wherever import BraceMessage as __
1071+ >>> print(__('Message with {0} {1}', 2, 'placeholders'))
1072+ Message with 2 placeholders
1073+ >>> class Point: pass
1074+ ...
1075+ >>> p = Point()
1076+ >>> p.x = 0.5
1077+ >>> p.y = 0.5
1078+ >>> print(__('Message with coordinates: ({point.x:.2f}, {point.y:.2f})',
1079+ ... point=p))
1080+ Message with coordinates: (0.50, 0.50)
1081+ >>> from wherever import DollarMessage as __
1082+ >>> print(__('Message with $num $what', num=2, what='placeholders'))
1083+ Message with 2 placeholders
1084+ >>>
1085+
1086+ One thing to note is that you pay no significant performance penalty with this
1087+ approach: the actual formatting happens not when you make the logging call, but
1088+ when (and if) the logged message is actually about to be output to a log by a
1089+ handler. So the only slightly unusual thing which might trip you up is that the
1090+ parentheses go around the format string and the arguments, not just the format
1091+ string. That's because the __ notation is just syntax sugar for a constructor
1092+ call to one of the XXXMessage classes.
1093+
1094+
9671095.. _zeromq-handlers :
9681096
9691097Subclassing QueueHandler - a ZeroMQ example
0 commit comments