When run, this script should say “Hello” and then “Goodbye” in a female voice. The above approach can, of course, be adapted to other TTS systems and even other systems altogether which can process messages via external programs run from a command line. There might be situations where you want to log messages in a temporary area and only output them if a certain condition occurs. For example, you may want to start logging debug events in a function, and if the function completes without errors, you don’t want to clutter the log with the collected debug information, but if there is an error, you want all the debug information to be output as well as the error. Here is an example which shows how you could do this using a decorator for your functions where you want logging to behave this way. It makes use of the$_{logging.handlers.MemoryHandler}$ , which allows buffering of logged events until some condition occurs, at which point the buffered events are$_{flushed}$- passed to another handler (the $_{target}$handler) for processing. By default, the$_{MemoryHandler}$ flushed when its buffer gets filled up or an event whose level is greater than or equal to a specified threshold is seen. You can use this recipe with a more specialised subclass of$_{MemoryHandler}$ if you want custom flushing behavior. The example script has a simple function, $_{foo}$, which just cycles through all the logging levels, writing to$_{sys.}$ stderr to say what level it’s about to log at, and then actually logging a message at that level. You can pass a parameter to $_{foo}$which, if true, will log at ERROR and CRITICAL levels - otherwise, it only logs at DEBUG, INFO and WARNING levels. The script just arranges to decorate$_{foo}$ with a decorator which will do the conditional logging that’s required. The decorator takes a logger as a parameter and attaches a memory handler for the duration of the call to the decorated function. The decorator can be additionally parameterised using a target handler, a level at which flushing should occur, and a capacity for the buffer (number of records buffered). These default to a $_{StreamHandler}$which writes to$_{sys.stderr}$ ,$_{logging.ERROR}$ and$_{100}$ respectively. Here’s the script: (continues on next page) (continued from previous page) 25 Buffering logging messages and outputting them conditionally 36 p.communicate() def configure_logging (): h =TTSHandler() root =logging.getLogger() root.addHandler(h) # the default formatter just returns the message root.setLevel(logging .DEBUG) def main(): logging.info('Hello') logging.debug( 'Goodbye ') if __name__ =='__main__ ': configure_logging() sys.exit(main()) import logging from logging.handlers import MemoryHandler import sys logger=logging.getLogger(__name__ ) logger.addHandler(logging .NullHandler()) def log_if_errors(logger, target_handler = None , flush_level = None , capacity = None ): if target_handler is None : target_handler=logging.StreamHandler()