Does any one out there have an example of how to setup logging in Python to a Tkinter Text Widget? I have seen this used in several apps but cannot figure out how to direct
I've bumped the same problem. The common solution found was like mentioned in this thread- bringing widget from GUI module to Logging.Handler.
It was criticized as not safety, as a widget is passes to another thread (logging).
The best solution found was using queue, made by Benjamin Bertrand:
https://beenje.github.io/blog/posts/logging-to-a-tkinter-scrolledtext-widget/.
I improved it a bit: queue should be created in logging handler, and passed to a GUI widget.
import logger
import queue
class QueueHandler(logging.Handler):
def __init__(self):
super().__init__()
self.log_queue = queue.Queue()
def emit(self, record):
# put a formatted message to queue
self.log_queue.put(self.format(record))
queue_handler = QueueHandler()
logger.addHandler(queue_handler)
So we have generally available logger, and every log message from any module will be passed to a queue_handler along with other handlers - to a file etc.
Now we can import queue_handler to a widget.
Most of the code is taken from the link above, I just changed the location of the original logging queue.
from tkinter.scrolledtext import ScrolledText
from some_logging_module import queue_handler
class ConsoleUi:
"""Poll messages from a logging queue and display them in a scrolled text widget"""
def __init__(self, frame, queue):
self.frame = frame
# Create a ScrolledText wdiget
self.console = ScrolledText(frame)
self.console.configure(font='TkFixedFont')
self.console.pack(padx=10, pady=10, fill=BOTH, expand=True)
self.log_queue = queue
# Start polling messages from the queue
self.frame.after(100, self.poll_log_queue)
def display(self, msg):
self.console.configure(state='normal')
self.console.insert(END, msg + '\n')
self.console.configure(state='disabled')
# Autoscroll to the bottom
self.console.yview(END)
def poll_log_queue(self):
# Check every 100ms if there is a new message in the queue to display
while not self.log_queue.empty():
msg = self.log_queue.get(block=False)
self.display(msg)
self.frame.after(100, self.poll_log_queue)
As result a widget displays all logging data of an app.