I created a simple UI for my application using curses and I also include logs (logging) in my modules using herarchy structure (logmain, logmain.child1) and so on.
I
You can create your own Handler
class to emit log messages to a curses
pad or window:
try:
unicode
_unicode = True
except NameError:
_unicode = False
class CursesHandler(logging.Handler):
def __init__(self, screen):
logging.Handler.__init__(self)
self.screen = screen
def emit(self, record):
try:
msg = self.format(record)
screen = self.screen
fs = "\n%s"
if not _unicode: #if no unicode support...
screen.addstr(fs % msg)
screen.refresh()
else:
try:
if (isinstance(msg, unicode) ):
ufs = u'\n%s'
try:
screen.addstr(ufs % msg)
screen.refresh()
except UnicodeEncodeError:
screen.addstr((ufs % msg).encode(code))
screen.refresh()
else:
screen.addstr(fs % msg)
screen.refresh()
except UnicodeError:
screen.addstr(fs % msg.encode("UTF-8"))
screen.refresh()
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
(This was basically copied from logging.StreamHandler
.)
The window or pad needs to be initialized to allow automatic scrolling etc.:
screen.nodelay(1)
maxy, maxx = screen.getmaxyx()
begin_x = 2; begin_y = maxy-5
height = 5; width = maxx-4
win = curses.newwin(height, width, begin_y, begin_x)
curses.setsyx(-1, -1)
screen.addstr("Testing my curses app")
screen.refresh()
win.refresh()
win.scrollok(True)
win.idlok(True)
win.leaveok(True)
mh = CursesHandler(win)
mh.setFormatter(formatterDisplay)
logger.addHandler(mh)
Here, screen
is the main curses
screen.
This code should work out of the box, The above didn't work for me.
import logging
import curses
import time
from curses import wrapper
class CursesHandler(logging.Handler):
def __init__(self, screen):
logging.Handler.__init__(self)
self.screen = screen
def emit(self, record):
try:
msg = self.format(record)
screen = self.screen
fs = "\n%s"
screen.addstr(fs % msg)
screen.box()
screen.refresh()
except (KeyboardInterrupt, SystemExit):
raise
except:
raise
def MainWindow(screen):
_unicode = True
win = screen.subwin(0,0)
win.box()
win.addstr(2,2,"Testing my curses app")
win1 = win.subwin(0,0)
win1.getch()
win1.refresh()
MAX_ROW, MAX_COL = win1.getmaxyx()
win1.scrollok(True)
win1.idlok(True)
win1.leaveok(True)
win1.setscrreg(4, MAX_ROW - 3)
win1.addstr(4, 4, "")
mh = CursesHandler(win1)
formatter = logging.Formatter(' %(asctime) -25s - %(name) -15s - %(levelname) -10s - %(message)s')
formatterDisplay = logging.Formatter(' %(asctime)-8s|%(name)-12s|%(levelname)-6s|%(message)-s', '%H:%M:%S')
mh.setFormatter(formatterDisplay)
logger = logging.getLogger('Test Logger')
logger.addHandler(mh)
i = 1
while True:
logger.error('message ' + str(i))
time.sleep(.128)
i+=1;
if __name__=="__main__":
wrapper(MainWindow)
Thanks to @zeeMonkeez I solved the problem. Below the complete code example:
import logging
import curses
import time
class CursesHandler(logging.Handler):
def __init__(self, screen):
logging.Handler.__init__(self)
self.screen = screen
def emit(self, record):
try:
msg = self.format(record)
screen = self.screen
fs = "\n%s"
if not _unicode: #if no unicode support...
screen.addstr(fs % msg)
screen.refresh()
else:
try:
if (isinstance(msg, unicode) ):
ufs = u'\n%s'
try:
screen.addstr(ufs % msg)
screen.refresh()
except UnicodeEncodeError:
screen.addstr((ufs % msg).encode(code))
screen.refresh()
else:
screen.addstr(fs % msg)
screen.refresh()
except UnicodeError:
screen.addstr(fs % msg.encode("UTF-8"))
screen.refresh()
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
try:
_unicode = True
screen = curses.initscr()
screen.nodelay(1)
maxy, maxx = screen.getmaxyx()
begin_x = 2; begin_y = maxy-5
height = 5; width = maxx-4
win = curses.newwin(height, width, begin_y, begin_x)
curses.setsyx(-1, -1)
screen.addstr("Testing my curses app")
screen.refresh()
win.refresh()
win.scrollok(True)
win.idlok(True)
win.leaveok(True)
mh = CursesHandler(win)
formatter = logging.Formatter('%(asctime) -25s - %(name) -15s - %(levelname) -10s - %(message)s')
formatterDisplay = logging.Formatter('%(asctime)-8s|%(name)-12s|%(levelname)-6s|%(message)-s', '%H:%M:%S')
mh.setFormatter(formatterDisplay)
logger = logging.getLogger('myLog')
logger.addHandler(mh)
for i in range(10):
logger.error('message ' + str(i))
time.sleep(1)
curses.curs_set(1)
curses.nocbreak()
curses.echo()
curses.endwin()
except NameError:
_unicode = False