Ipywidgets: Logging to an output widget (as opposed to print with context manager)

Created on 26 Jan 2018  路  6Comments  路  Source: jupyter-widgets/ipywidgets

Following discussion with @jasongrout, a rough version of how I accomplished logging to an Output widget.

Benefits of this method are:

  • Avoid repeated calls to with output: and print throughout code
  • Can configure several logging with different handlers; route your logging messages to different Output widgets.

The particular configuration I used here means that logging messages always appear on top of the Output widget, and force newer messages to the bottom.

Credit: https://stackoverflow.com/questions/3290292/read-from-a-log-file-as-its-being-written-using-python for the code to subclass the handler and extend the emit() method.

import logging
from colorama import Fore
import ipywidgets as ipyw

out = ipyw.Output(layout=ipyw.Layout(width='600px', height='160px', border='solid'))

class log_viewer(logging.Handler):
    """ Class to redistribute python logging data """

    # have a class member to store the existing logger
    logger_instance = logging.getLogger("__name__")

    def __init__(self, *args, **kwargs):
         # Initialize the Handler
         logging.Handler.__init__(self, *args)

         # optional take format
         # setFormatter function is derived from logging.Handler
         for key, value in kwargs.items():
             if "{}".format(key) == "format":
                 self.setFormatter(value)

         # make the logger send data to this class
         self.logger_instance.addHandler(self)

    def emit(self, record):
        """ Overload of logging.Handler method """

        record = self.format(record)
        out.outputs = ({'name': 'stdout', 'output_type': 'stream', 'text': (Fore.BLACK + (record + '\n'))},) + out.outputs

main_logger = logging.getLogger(__name__)
main_logger.addHandler(log_viewer())
main_logger.setLevel(20)   # log at info level.

You can log to the widget from anywhere (provided you have imported main_logger) by calling `main_logger.info('msg text'), and possibly alter the color (hence colorama).

docs good first issue

All 6 comments

This is great! There's an issue for centralising the documentation on the output widget (issue #1935 ). Maybe this recipe should go in there?

Would it also make sense to add a convenience method to the Output widget to give you back one of these log viewer instances specific to the widget?

Thanks for posting this!

This block:

         # optional take format
         # setFormatter function is derived from logging.Handler
         for key, value in kwargs.items():
             if "{}".format(key) == "format":
                 self.setFormatter(value)

is probably more natural as
```python

set an optional formatter

if 'format' in kwargs:
self.setFormatter(kwargs['format'])
````

Setting to good first issue - we can both add it to the output docs (see #1935) and add a convenience method to return a logger.

I've created a pull request https://github.com/jupyter-widgets/ipywidgets/pull/2268 to implement the convenience function, if it looks good, I'll update the docs based on the function.

Was this page helpful?
0 / 5 - 0 ratings