【问题标题】:How to continuously read from stdin (not just once input file is done)?如何从标准输入连续读取(不仅仅是输入文件完成后)?
【发布时间】:2022-01-12 21:48:54
【问题描述】:

我有这两个脚本:

时钟.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
...

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

【问题讨论】:

  • 你需要刷新clock.py中的stdout缓冲区。
  • print("True", flush=True)
  • 问题不在于读取,而在于写入管道。
  • 您应该在continuous_wc.py 中的计数后写一个换行符,因为您希望每个数字位于不同的行。这也将解决问题,因为输出是行缓冲的。
  • 你为什么使用sys.stdinsys.stdout,而不是input()print()

标签: python stdout stdin sys


【解决方案1】:

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

请注意,从技术上讲,这些程序可以在没有刷新的情况下工作,但它们会以非常大的块非常不频繁地打印值,因为 Python IO 缓冲区有很多千字节。刷新是为了让它更实时地工作。

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

【讨论】:

    【解决方案2】:

    根据大家的建议,这就是我现在所拥有的(有效):

    时钟.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 也可以。

    【讨论】: