(continued from previous page) try : # loop through logging calls to see the difference # new configurations make, until Ctrl+C is pressed while True : logger.debug( 'debug message') logger.info('info message') logger.warning( 'warn message') logger.error('error message') logger.critical( 'critical message') time.sleep( 5) except KeyboardInterrupt: # cleanup logging.config.stopListening() t.join() #!/usr/bin/env python import socket , sys , struct with open(sys.argv[1],'rb') as f: data_to_send=f.read() HOST ='localhost' PORT =9999 s =socket.socket(socket .AF_INET, socket.SOCK_STREAM) print('connecting... ') s.connect((HOST, PORT)) print('sending config... ') s.send(struct .pack( '>L',len(data_to_send))) s.send(data_to_send) s.close() print('complete') And here is a script that takes a filename and sends that file to the server, properly preceded with the binary-encoded length, as the new logging configuration: Sometimes you have to get your logging handlers to do their work without blocking the thread you’re logging from. This is common in Web applications, though of course it also occurs in other scenarios. A common culprit which demonstrates sluggish behaviour is the$_{SMTPHandler}$ : sending emails can take a long time, for a number of reasons outside the developer’s control (for example, a poorly performing mail or network infrastructure). But almost any network-based handler can block: Even a$_{SocketHandler}$operation may do a DNS query under the hood which is too slow (and this query can be deep in the socket library code, below the Python layer, and outside your control). One solution is to use a two-part approach. For the first part, attach only a$_{QueueHandler}$to those loggers which are accessed from performance-critical threads. They simply write to their queue, which can be sized to a large enough capacity or initialized with no upper bound to their size. The write to the queue will typically be accepted quickly, though you will probably need to catch the$_{queue.Full}$ exception as a precaution in your code. If you are a library developer who has performance-critical threads in their code, be sure to document this (together with a suggestion to attach only$_{QueueHandlers}$to your loggers) for the benefit of other developers who will use your code. The second part of the solution is $_{QueueListener}$, which has been designed as the counterpart to $_{QueueHandler}$. A QueueListener is very simple: it’s passed a queue and some handlers, and it fires up an internal thread which listens to its queue for LogRecords sent from$_{QueueHandlers}$(or any other source of 7 6 Dealing with handlers that block