在curses中将内容打印到标准控制台

11

我正在构建一个Python curses应用程序。

我有两种方法可以输出到curses窗口:print xwindows.addstr(x)(以及其他类似的window.*选项)。

然而,出于调试目的,我想能够打印到标准控制台,这样当我退出curses窗口时,我就有等待查看的信息。我通常会使用print x,但那会在curses窗口中打印。

sys.stout.write()也无法正常工作。

我该怎么做呢?

在使用os.fdopen之后使用sys.stdout后,这是回溯信息。

 curses.nocbreak()
 _curses.error: nocbreak() returned ERR
 close failed in file object destructor:
 sys.excepthook is missing
 lost sys.stderr

1
你尝试过使用 sys.stdout.write() 吗?但是它也可能被重定向了,这种情况下你可以尝试使用 open(1, 'w')(fd 1 是标准输出)。 - Martijn Pieters
@Martijn sys.sdout.write() 也失败了。同时,open(1, 'w') 也失败了,它需要一个字符串作为文件名。 - ACarter
1
@ACarter Martijn 可能意思是 os.fdopen。无论如何,我认为你应该使用 logging 模块并记录到文件中。 - Bakuriu
如果print输出到标准输出以外的地方,我认为sys.stdout已经被100%重定向了。 - jadkik94
@jadkik94:我怀疑sys.stdout被重定向了,因此尝试打开fd 1。对于Python 2来说,确实可以使用os.fdopen(1, 'w') - Martijn Pieters
@Martjin,啊啊啊,那有点毁了它,看看我编辑过的堆栈跟踪。 - ACarter
2个回答

13

为了按照您的要求,这是我使用的片段:

class StdOutWrapper:
    text = ""
    def write(self,txt):
        self.text += txt
        self.text = '\n'.join(self.text.split('\n')[-30:])
    def get_text(self,beg,end):
        return '\n'.join(self.text.split('\n')[beg:end])

if __name__ == "__main__":
    mystdout = StdOutWrapper()
    sys.stdout = mystdout
    sys.stderr = mystdout

    screen = curses.initscr()
    curses.noecho()
    curses.cbreak()

    # do your stuff here
    # you can also output mystdout.get_text() in a ncurses widget in runtime

    screen.keypad(0)
    curses.nocbreak()
    curses.echo()
    curses.endwin()
    sys.stdout = sys.__stdout__
    sys.stderr = sys.__stderr__
    sys.stdout.write(mystdout.get_text())

使用这个技巧的好处是,您可以在ncurse运行时在小部件中输出stdout。当然,StdOutWrapper的内部表示可以根据您的需要进行调整,以更好地匹配您的需求。


1
这是一个有趣的解决方案,我以前从未想过。谢谢。 - ACarter

2
为什么不使用标准的logging模块呢?
将其与curses.wrapper结合使用,你就可以开始了。
“EDIT:”
“你可以在这里看到示例:https://dev59.com/DF4c5IYBdhLWcg3wj7F6#28102809
“如果你只想将日志记录到文件中:”
import logging
import curses

def draw(stdscr):
    logger = logging.getLogger(__file__)
    hdlr = logging.FileHandler(__file__ + ".log")
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
    hdlr.setFormatter(formatter)
    logger.addHandler(hdlr)
    logger.setLevel(logging.DEBUG)

    logger.info("begin")

    curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK)
    stdscr.addstr(0, 0, 'hello', curses.color_pair(1))
    logger.info("yeah")
    stdscr.getch()
    logger.info("end")


if __name__ == '__main__':
    curses.wrapper(draw)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接