stdin不应该等待" CTRL + D"

时间:2014-08-08 10:38:12

标签: python stdin

我有一个简单的python脚本应该从stdin读取。 所以,如果我将程序的stdout重定向到stdin到我的python脚本。

但是我的程序记录到python脚本的东西只会在记录这些东西的程序被杀死时“到达”python脚本。

但实际上我想处理我的程序一旦可用就记录的每一行,而不是当我的程序应该实际全天候运行时退出。

那我该如何实现呢?在处理数据之前,如何让stdin不等待CTRL + D或EOF?

实施例

# accept_stdin.py
import sys
import datetime

for line in sys.stdin:
    print datetime.datetime.now().second, line

# print_data.py
import time

print "1 foo"
time.sleep(3)
print "2 bar"

# bash
python print_data.py | python accept_stdin.py

3 个答案:

答案 0 :(得分:3)

与所有文件对象一样,sys.stdin迭代器以块的形式读取输入;即使输入行准备就绪,迭代器也会在输出任何内容之前尝试读取块大小或EOF。您可以使用readline方法解决此问题,该方法没有此行为:

while True:
    line = sys.stdin.readline()
    if not line:
        # End of input
        break
    do_whatever_with(line)

您可以将其与iter的双参数形式结合使用for循环:

for line in iter(sys.stdin.readline, ''):
    do_whatever_with(line)

我建议在代码中留下注释,说明为什么不使用常规迭代器。

答案 1 :(得分:3)

这也是你的生产者程序的问题,即你将stdout传递给python脚本的程序。

实际上,由于此程序只打印并且从不刷新,因此打印的数据保存在stdout的内部程序缓冲区中,而不会刷新到系统中。

sys.stdout.flush() print后的print_data.py语句后立即添加{{1}}来电。

退出程序时会看到数据,因为它会在退出时自动刷新。

请参阅this问题以获取解释,

答案 2 :(得分:1)

正如@ user2357112所说,您需要使用:

for line in iter(sys.stdin.readline, ''):

之后你需要用-u标志启动python以立即刷新stdin和stdout。

python -u print_data.py | python -u accept_stdin.py

您还可以在shebang中指定标志。