从管道读取Python stdin,而不会阻塞空输入

时间:2018-11-29 14:26:57

标签: python pipe stdin blocking nonblocking

从管道接收消息时,我试图用Python脚本读取stdin。

我用了以下几行:

for line in sys.stdin:
    print line

并运行脚本:echo "test" | script.py

到目前为止,它工作正常。但是,如果我不使用管道,则程序会停留在for命令中。这意味着调用:./script.py将使脚本不起作用。我该如何解决?

3 个答案:

答案 0 :(得分:2)

编辑:在这种情况下,您显然甚至不希望它读取行或处理python3,因此您需要做的是检查空KeyboardInterrupt。如编辑的示例所示,检查您是否是终点站并通过。


stdin类似于文件。试试:

sys.stdin

如果您在没有if not sys.stdin.isatty(): data = sys.stdin.readlines() # Do something with data 的情况下运行此程序,我认为它不会像以前那样为您挂起...,因为stdin将为空。然后该功能应继续。

答案 1 :(得分:1)

您的脚本有效,似乎您的期望不正确。

script.py(针对我安装的Python 3进行了调整):

import sys
for line in sys.stdin:
    print(line)
  

$ python script.py
  abcd
  abcd

     

xyz
  xyz

第一次出现的“ abcd”和“ xyz”是我从键盘输入的,第二次出现是程序的输出。我当时通过ctrl-d终止了执行。

问题在于,从标准输入中读取数据而没有管道输入并不能满足您的期望。当您只运行脚本(没有管道输入)时,它就坐在那里等待您从键盘输入内容。您可能需要调查raw_input以便从键盘上获取输入。

更新

在对您想要的内容发表评论后,以下脚本可能会为您提供所需的结果:

import sys
if not sys.stdin.isatty():
    for line in sys.stdin:
        print(line)

print("More stuff!")

答案 2 :(得分:1)

您可以通过从isatty派生的文件描述符上调用sys.stdin来检查程序是否已通过管道传输。

就像这样:

import os
import sys

if not os.isatty(sys.stdin.fileno()):
    print (sys.stdin.readlines())
else:
    print ("Skip, so it doenst hang")

示例1:

 echo "test" | python ./script.py
 ['test\n']

示例2:

 python ./script.py 
 Skip, so it doenst hang