如何检查stdin是否包含一些数据?


69

在Python中,如何检查是否sys.stdin有数据?

我发现不仅os.isatty(0)可以检查stdin是否已连接到TTY设备,还可以检查是否有可用数据。

但是如果有人使用诸如

sys.stdin = cStringIO.StringIO("ddd")

然后使用os.isatty(0),它仍然返回True。我需要做什么检查stdin是否有数据?


3
您到底想实现什么?
shahjapan

这是因为os.isatty(0)检查与文件描述符(fd)0关联的文件是否为TTY。更改sys.stdin变量时,不会更改与fd0关联的文件。fd0仍指向原始stdin(在您的情况下为TTY)。
Cristian Ciupitu

2
检查此答案。与您的问题有关吗?
Muhammad Alkarouri 2010年

@Cristian Ciupitu,您是对的,我使用sys.stdin = cStringIO.String(“ ddd”)重定向标准输入,如果我使用sys.stdin.read( )将直接阻止以下内容,并始终等待(如果未提供任何输入)
mlzboy 2010年

我看不到如何cStringIO.StringIO("ddd")阻止阅读;它始终具有可用数据,当然达到EOF时除外。
Cristian Ciupitu

Answers:


77

在Unix系统上,您可以执行以下操作:

import sys
import select

if select.select([sys.stdin,],[],[],0.0)[0]:
    print "Have data!"
else:
    print "No data"

在Windows上,虽然select模块只能与套接字一起使用,所以您需要使用其他机制。


对不起,我必须删除接受,因为我使用sys.stdin = cStringIO.StringIO(“ ddd”)将stdin重定向到模拟文件,但是它没有fileno方法,我用您编写的代码将如果未选择,则引发select.select([sys.stdin],[],[],0.0)[0]:TypeError:参数必须为int或具有fileno()方法。
mlzboy

2
@mlzboy:只有由操作系统打开的“真实”文件才具有文件描述符号(Unix套接字或管道上的顺便说一句也是文件)。select调用操作系统的选择功能的文件只能与这些文件一起使用。StringIO是仅Python解释器已知的虚拟文件,因此它没有文件描述符,因此无法select在其上使用。
Cristian Ciupitu

2
@mlzboy管道的缓冲区大小有限。写入没有任何读取内容的管道是危险的,因为如果尝试写入的内容超出缓冲区大小,它将阻塞(死锁)。
Aryeh Leib Taurog 2014年

1
在由cron执行的脚本中使用时,此方法对我来说失败了。sys.stdin.isatty()但是确实在cron中为我工作。
戴夫

1
在詹金斯,退货不行的<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>,而不是[]
GuySoft

68

我一直在用

if not sys.stdin.isatty()

这是一个例子:

import sys

def main():
    if not sys.stdin.isatty():
        print "not sys.stdin.isatty"
    else:
        print "is  sys.stdin.isatty"

跑步

$ echo "asdf" | stdin.py
not sys.stdin.isatty

sys.stdin.isatty()如果中包含,则返回false stdin

isatty(...)
    isatty() -> true or false. True if the file is connected to a tty device.

5
谢谢!这比使用容易得多select
Niklas R 2014年

谢谢。那解决了我的问题:echo'也许管道'| Linux上的stdin.py + maybe_args。melancholynaturegirl的解决方案可以在Windows上使用吗?
Alexx Roche

看来... C:\ Users \ naturegirl \ Desktop> C:\ Python27 \ python.exe isatty.py是sys.stdin.isatty C:\ Users \ naturegirl \ Desktop> C:\ Users \ naturegirl \ Desktop>回声“ foo” | C:\ Python27 \ python.exe isatty.py不是sys.stdin.isatty
Erin

23
这不是一个好主意。如果从文件中输入标准输入怎么办?isatty()告诉您stdin是否直接从终端进入,而不是是否有更多数据要从stdin读取
Lathan

2
由于grep在另一篇文章中提到,我会提到less用途isatty。我来这里的目的是想做些什么less:如果将文件路径作为输入参数给出,则从文件中读取输入,否则从stdin中读取输入。一种替代方法是-用作stdin的别名,并只接受file参数。
ws_e_c421 '18

4

根据此处的目标:

import fileinput
for line in fileinput.input():
    do_something(line)

也可能有用。


AFAIK,fileinput有一个缺点,它限制了args必须是文件名,但是我的args可能是一些控制命令,
mlzboy 2010年

很公平!我正在尝试处理“可能对stdin进行一些处理”这句话的惯用语:)
Gregg Lind 2010年

3

(编辑:这回答了一个相关的问题,此问题已在此处合并。)

就像其他人提到的那样,没有万无一失的方法来知道是否可以从stdin获得数据,因为UNIX不允许这样做(更普遍的是,因为它无法猜测stdin连接到的任何程序的未来行为)。

始终等待标准输入,即使可能什么也没做(就是这样做grep等等),或要求用户提供-参数。


1
那么,您是通过引用相同的问题来回答问题吗?WTF ??
ForceBru

@ForceBru这确实非常令人困惑,哈哈。似乎在这里合并了另一个问题。我已编辑。
n.caillou

过程将是什么-等待stdin并读取直到EOF,然后处理数据?也就是说,grep等人如何做。知道何时处理数据以及何时退出?
马特

1
@Matt上游数据源负责发送EOF。例如printf "" | catwhile read l; do true; done; echo finishing(在第二种情况下,您必须手动输入EOF / ^ D才能通过)
n.caillou

ps注意,如果仅cat在命令行上输入例如,它将无限期地等待输入。在上面的示例中,printf发送EOF
n.caillou

0

使用内置模块,可以通过以下代码来实现,因为Greg已经给出了这个想法:

import fileinput
isStdin = True
for line in fileinput.input:
    # check if it is not stdin
    if not fileinput.isstdin():
        isStdin = False
        break
    # continue to read stdin
    print(line)
fileinput.close()


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.