Python中的动态多行刷新打印

2 投票
1 回答
1479 浏览
提问于 2025-04-17 22:43

我刚接触Python,有些事情我搞不明白。

我想做的事情:

我希望能够在控制台上动态地重写多行输出。我见过很多关于单行输出的解决方案,但多行输出的解决方案就少得多。下面这些Stack Overflow的帖子和我的问题有点相似,但并没有完全解决我的问题(我稍后会解释原因):

Python - 在控制台重写多行

Python中的多进程或多线程动态刷新打印

另外,我还希望能够将输出重定向到文件或管道(比如说,如果我运行 ./script.py > out.txt,然后中断这个过程,我希望中间的进度条也能写入输出文件)。

我为什么想这样做?

我正在尝试解析一个持续的Json流,格式大概是这样的:

{
...valid Json data block...
},{
...Another valid Json data block...
}, etc...

最后我希望得到的结果是这样的(我需要帮助的过程是过滤出唯一的Json块):

./generate-stream | ./filter-single-view | ./json-processing

注意:我使用Json并不影响我的问题,我主要提到它是为了给你提供一个背景。我的想法就是有一个脚本管道,生成多个数据,过滤出一个数据,然后处理这个数据。

我已经把流解析成了一个字符串,里面有我想打印的Json块(然后再打印下一个,会覆盖掉它)。

动态刷新的示例:

{
"i": 0
}

控制台输出步骤1(我已经把所有信息存储在一个字符串里)

{
"i": 1
}

控制台输出步骤2

{
"i": 2
}

控制台输出步骤3,等等……

因此,第一个帖子给出的答案不适合我的问题,因为我无法输出结果,而第二个答案也不适用,原因相同。此外,这种清屏的方式会搞乱数据,导致在下一个处理过程中无法正确使用。还有一个解决我问题的方法就是找到一种方法持续忽略清屏字符(我试过忽略前面的字符,第一次输入有效,但之后就全乱了)。

如果有什么不清楚的地方,请告诉我。谢谢!

1 个回答

0

我解决了我的问题!

我之前提到过流的格式,不用担心解析的细节。这段代码可以解析这个流,并单独显示Json数据。

    import sys
    import json
    import os

    def main(): 
        json_string=""
        try:
            while True:
                line=sys.stdin.readline()
                if line!="},{\n":
                    json_string=json_string+line
                    continue
                else:
                    #Output singular Json data
                    json_string=json_string+"}\n"
                    json_data=json.loads(json_string)
                    json.dump(json_data, sys.stdout) 
                    os.system('cls' if os.name == 'nt' else 'clear')
                    sys.stdout.flush() 
                    json_string="{\n" 
        except KeyboardInterrupt:
            sys.stdin.close()
            print "Interrupted by user. Bye!"  

    if __name__ == "__main__":
        main()

现在,我想把这个单独的数据在另一个脚本中读取,作为输入(stdin)。我不是很明白为什么,但任何读取操作都会被阻塞。因此,我实现了以下内容。

    import sys
    import json
    import os

    k = 0
    parsing=False
    try:
        buff = ''
        while True:
            #The 2 following functions are blocking
            #buff= sys.stdin.readline()
            #buff = json.load(sys.stdin)
            buff += sys.stdin.read(1)
            if buff.endswith('{'):
                parsing=True;
                k+=1
            if buff.endswith('}'):
                k-=1
            if k==0 and parsing:
                print buff
                #The first 7 characters clear the screen
                data=json.loads(buff[7:])
                buff = ''
                parsing=False

    except KeyboardInterrupt:
       sys.stdout.flush()
       pass

如果你对此有任何意见,请告诉我。

撰写回答