如何持续从 stdin 中读取(不仅仅是一次性读取完输入文件)?

4

I have these two scripts:

clock.py

#!/usr/bin/env python3
import time

while True: 
    print("True", flush=True)
    time.sleep(1)

continuous_wc.py

#!/usr/bin/env python3
import sys

def main():
    count = 0
    for line in sys.stdin:
        sys.stdout.write(str(count))
        count += 1

if __name__=='__main__':
    main()

然后我像这样运行它们:

./clock.py | ./continuous_wc.py

我希望它会打印出以下内容:
1
2
3
4
5
...

每一秒钟都像一个时钟,因为它基本上正在计算文件中的行数。但它不输出任何内容。为什么?

每秒钟计算的是文件的行数,但程序并没有输出这个计算结果。原因在于代码没有添加输出的逻辑。


2
print("True", flush=True) - Barmar
2
问题不在于读取,而在于向管道写入。 - Barmar
1
@Barmar 谢谢你。我已经根据你的建议更新了问题。但似乎仍然没有任何输出。 - BigBoy1337
2
continuous_wc.py 中的计数后面应该写一个换行符,因为你希望每个数字都在不同的行上。这也将解决问题,因为输出是行缓冲的。 - Barmar
2
你为什么要使用 sys.stdinsys.stdout,而不是 input()print() - Barmar
显示剩余4条评论
2个回答

4

除了 print(x, flush=True) 之外,您还必须在 sys.stdout.write 之后进行刷新。

请注意,程序在没有刷新的情况下也可以正常工作,但是它们会非常不频繁地打印值,并且以很大的块为单位打印,因为Python IO缓冲区有多个千字节。刷新是为了使其更加实时地运行。

sys.stdout.write(str(count))
sys.stdout.flush()

3

经过大家的建议,这是我现在拥有的代码(并且它可以工作):

clock.py

#!/usr/bin/env python3
import time

while True:
    print("True", flush=True) 
    time.sleep(1)

continuous_wc.py

#!/usr/bin/env python3
import sys

def main():
    count = 0
    for line in sys.stdin:
        print(count, flush=True, end='\r')
        count += 1

if __name__=='__main__':
    main()

在写和读脚本中,我不得不使用 flush=True。然而,在使用 PYTHONUNBUFFERED=1 时,我可以跳过这一步并且它可以正常工作。感谢 @Mark Setchell。此外,我正在使用 printstdin,但似乎 fileinput.input 也可以使用。


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