如何管理登录curses
Posted
技术标签:
【中文标题】如何管理登录curses【英文标题】:How to manage logging in curses 【发布时间】:2015-03-02 16:04:42 【问题描述】:我使用 curses 为我的应用程序创建了一个简单的 UI,我还使用层次结构(logmain、logmain.child1)等在我的模块中包含了日志(日志记录)。
如果发生日志事件,日志会显示在我的 UI 中,从而破坏其外观。 我还创建了一个垫(myLogPad),以便将传入的日志放在那里,但没有成功。 如何拦截日志事件并将其打印在屏幕的特定区域(最后一行)?
def setupLogger(name,file_name):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
#formatter = logging.Formatter(
# "%(asctime)s %(threadName)-11s %(levelname)-10s %(message)s")
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')
# Alternative formatting available on python 3.2+:
# formatter = logging.Formatter(
# "asctime threadName:>11 levelname message", style='')
# Log to file
filehandler = logging.FileHandler(file_name, 'w')
filehandler.setFormatter(formatter)
logger.addHandler(filehandler)
# Log to stdout too
streamhandler = logging.StreamHandler()
streamhandler.setFormatter(formatterDisplay)
logger.addHandler(streamhandler)
我尝试在 streamhandler = logging.StreamHandler() 中传递 mylog pad,但没有成功。 任何想法? 谢谢
【问题讨论】:
【参考方案1】:您可以创建自己的Handler
类来将日志消息发送到curses
板或窗口:
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)
(这基本上是从logging.StreamHandler
复制而来的。)
需要初始化窗口或 pad 以允许自动滚动等:
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)
这里,screen
是 curses
的主屏幕。
【讨论】:
谢谢 zeeMonkeez。我完全听从了你的建议,明白了!下面我添加了压轴示例。【参考方案2】:感谢@zeeMonkeez,我解决了这个问题。 下面是完整的代码示例:
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
【讨论】:
【参考方案3】:这段代码应该可以开箱即用,上面的代码对我不起作用。
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)
【讨论】:
以上是关于如何管理登录curses的主要内容,如果未能解决你的问题,请参考以下文章