(continued from previous page) >>> p.x =0.5 >>> p.y =0.5 >>> print(__( 'Message with coordinates: ( {point.x:.2f} , {point.y:.2f} )', ... point=p)) Message with coordinates: (0.50, 0.50) >>> from wherever import DollarMessage as __ >>> print(__( 'Message with $num $what ', num =2, what='placeholders')) Message with 2 placeholders >>> import logging classMessage : def __init__ (self, fmt, args): self.fmt =fmt self.args =args def __str__ (self): return self.fmt.format( *self.args) classStyleAdapter (logging .LoggerAdapter): def __init__ (self, logger, extra = None ): super() .__init__ (logger, extra or {}) def log(self, level, msg, /,*args,**kwargs): if self.isEnabledFor(level): msg, kwargs=self.process(msg, kwargs) self.logger._log(level, Message(msg, args), (), **kwargs) logger=StyleAdapter(logging .getLogger(__name__ )) def main(): logger.debug( 'Hello, {} ','world! ') if __name__ =='__main__ ': logging.basicConfig(level =logging.DEBUG) main() The above script should log the message$_{Hello, world!}$ when run with Python 3.2 or later. If you prefer, you can use a$_{LoggerAdapter}$ to achieve a similar effect to the above, as in the following example: One thing to note is that you pay no significant performance penalty with this approach: the actual formatting happens not when you make the logging call, but when (and if) the logged message is actually about to be output to a log by a handler. So the only slightly unusual thing which might trip you up is that the parentheses go around the format string and the arguments, not just the format string. That’s because the __ notation is just syntax sugar for a constructor call to one of the XXXMessage classes. While the above examples use$_{print()}$ to show how the formatting works, you would of course use$_{logger.}$ debug() or similar to actually log using this approach. 20