#coding=utf-8 import datetime import logging as log from collections import OrderedDict import tkinter as tk from tkinter import ttk import tkFileDialog as tkfd class LogWindow(tk.Toplevel): def __init__(self, *args, **kwargs): tk.Toplevel.__init__(self, *args, **kwargs) self.withdraw() self.protocol('WM_DELETE_WINDOW', self.withdraw) self.renderContents() self._records = [] self._counter = -1 self._registerLogging() def renderContents(self): columns = [ ('level', 'Poziom komunikatu', 150), ('category', 'Moduł', 150), ('message', 'Komunikat', None)] self.logList = ttk.Treeview( self, show='headings', columns=[c[0] for c in columns], selectmode='browse') for column, heading, width in columns: self.logList.heading(column, text=heading) if width is not None: self.logList.column(column, width=width, stretch=False) else: self.logList.column(column, stretch=True) self.logList.pack(side=tk.TOP, fill=tk.BOTH, expand=True) btnFrame = tk.Frame(self) btnFrame.pack(side=tk.BOTTOM) (ttk.Button( btnFrame, text='Zapisz dziennik...', command=self.onRecordsSave)).pack(side=tk.LEFT) (ttk.Button( btnFrame, text='Wyczyść dziennik', command=self.resetRecords)).pack(side=tk.LEFT) def _getGUIHandler(self): return LogHandler(log.INFO, window=self) def _getConsoleHandler(self): consoleHandler = log.StreamHandler() consoleHandler.setFormatter( log.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s')) return consoleHandler def _registerLogging(self): logger = log.getLogger() logger.setLevel(log.INFO) for handler in [self._getConsoleHandler, self._getGUIHandler]: logger.addHandler(handler()) def addRecord(self, record): self._counter += 1 self._records.append((record, datetime.datetime.now())) if not isinstance(record.message, unicode): record.message = unicode(record.message, errors='replace') self.logList.insert( '', tk.END, tag=self._counter, values=[ record.levelname, record.name, record.message ]) self.logList.yview_moveto(1) def resetRecords(self): self._records = [] self.logList.delete(*self.logList.get_children()) def onRecordsSave(self, *args): filename = tkfd.asksaveasfilename( title='Wybierz plik dziennika', filetypes=(('Log files', '*.log'),)) if filename: if not filename.lower().endswith('.log'): filename = filename + '.log' self._saveRecords(filename) def _saveRecords(self, filename): with open(filename, 'w') as fileObj: for record, timestamp in self._records: fileObj.write(( u'%s\t%s\t%s\t%s\n' % ( timestamp, record.levelname, record.name, record.message)).encode( 'utf8')) class LogHandler(log.Handler): def __init__(self, *args, **kwargs): self._window = kwargs['window'] del kwargs['window'] log.Handler.__init__(self, *args, **kwargs) def handle(self, record): self.format(record) self._window.addRecord(record)