#!/usr/bin/env python # coding: utf-8 # # Continuous capture of output from wurlitzer to a logger # # Illustration for [minrk/wurlitzer#76](https://github.com/minrk/wurlitzer/issues/76). # # First, set up a logger. This one logs to stdout and includes the timestamp, # so we can see how often log lines are produced. # In[37]: import logging logger = logging.getLogger("test-log-pipe") logger.handlers[:] = [] logger.setLevel(logging.INFO) h = logging.StreamHandler(sys.stdout) h.setLevel(logging.INFO) h.setFormatter(logging.Formatter("[{name} {asctime}] {msg}", style="{")) logger.addHandler(h) logger.info("test message") # Next, we need to create a Writable (anything with a `write` method), # which will take lines and put them onto the logger # In[38]: import io class LogPipe(io.BufferedWriter): """Writeable that writes lines to a Logger object as they are written""" def __init__(self, logger): self.logger = logger self.buf = "" def write(self, chunk): """Given chunk, split into lines Log each line as a discrete message If it ends with a partial line, save it until the next one """ if self.buf: chunk = self.buf + chunk lines = chunk.splitlines(True) if not lines[-1].endswith("\n"): self.buf = lines[-1] lines = lines[:-1] else: self.buf = "" for line in lines: self.logger.info(line.rstrip()) pipe = LogPipe(logger) # Test it out: pipe anything written to low-level stderr to our logger (which writes to stdout) # In[39]: import sys import time import wurlitzer logger.info("start") with wurlitzer.pipes(stdout=None, stderr=pipe): for i in range(15): sys.__stderr__.write(f"step {i}\n") time.sleep(0.1) logger.info("end")