如何检查标准输入是不是有一些数据?

Posted

技术标签:

【中文标题】如何检查标准输入是不是有一些数据?【英文标题】:How do I check if stdin has some data?如何检查标准输入是否有一些数据? 【发布时间】:2011-04-15 08:11:41 【问题描述】:

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

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

但是如果有人使用诸如

之类的代码
sys.stdin = cStringIO.StringIO("ddd")

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

【问题讨论】:

你到底想达到什么目的? 发生这种情况是因为os.isatty(0) 检查与文件描述符 (fd) 0 关联的文件是否为 TTY。当您更改 sys.stdin 变量时,您不会更改与 fd0 关联的文件。 fd0 仍然指向原始标准输入(在您的情况下是 TTY)。 检查this answer。是否与您的问题有关? @Cristian Ciupitu,你是对的,我使用 sys.stdin=cStringIO.String("ddd") 重定向标准输入,我想要的是如何检查 sys.stdin 是否有数据,如果我直接使用 sys.stdin.read() 它会阻塞下面的东西,如果没有输入,它会一直等待 我看不到来自cStringIO.StringIO("ddd") 的读取会如何阻塞;它总是有可用的数据,当然,除非达到 EOF。 【参考方案1】:

在上面看到了很多答案,其中几乎所有的答案都需要 sys、select、os 等。但是,我有一个非常简单的想法,即如果有数据,如何从 stdin 连续获取输入。 我们可以使用 try, except 块来这样做。 作为,

while(1):
  try:
    inp = input()
  except:
     break

上面的循环将运行,我们不断检查输入并将输入存储在变量“inp”中,如果标准输入中没有输入,那么尝试将抛出错误,但是在除了块中断语句存在,所以while 循环将被终止

【讨论】:

但是程序会等待输入并暂停执行。你不能根据 stdin 是否为空来做某事。【参考方案2】:

我一直在用

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

如果stdin 未连接到交互式输入设备(例如 tty),sys.stdin.isatty() 返回 false。

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

【讨论】:

谢谢!这比使用select 容易得多。 谢谢。这解决了我的问题:echo '也许管道' | linux 上的 stdin.py +maybe_args。 melancholynaturegirl 的解决方案是否适用于 windows? 看来... C:\Users\naturegirl\Desktop>C:\Python27\python.exe isatty.py 是 sys.stdin.isatty C:\Users\naturegirl\Desktop> C :\Users\naturegirl\Desktop>echo "foo" | C:\Python27\python.exe isatty.py 不是 sys.stdin.isatty 这不是一个好主意。如果标准输入是从文件中输入的怎么办? isatty() 告诉您标准输入是否直接从终端输入,而不是告诉您是否有更多数据要从标准输入读取 由于grep 在另一篇文章中被提及,我将提到less 使用isatty。我来这里是为了做类似less 的事情:如果文件路径作为输入参数给出,则从文件读取输入,否则从标准输入读取输入。另一种方法是使用- 作为stdin 的别名并只接受文件参数。【参考方案3】:

使用内置模块,这可以通过以下代码来实现,因为 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()


【讨论】:

fileinput.input 是一个不可迭代的函数,当没有数据时它会永远阻塞【参考方案4】:

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

正如其他人所提到的,没有万无一失的方法可以知道数据是否可以从标准输入获得,因为 UNIX 不允许这样做(更一般地说,因为它无法猜测标准输入连接到的任何程序的未来行为)。

始终等待标准输入,即使可能什么都没有(这就是 grep 等所做的),或者向用户询问 - 参数。

【讨论】:

那么,您是通过引用同一个问题来回答问题吗? WTF?? @ForceBru 这确实很混乱,哈哈。似乎这里合并了另一个问题。我已经编辑了。 这个过程是什么 - 等待标准输入并读取直到 EOF,然后处理数据?也就是说,grep 等人如何做。知道何时处理数据以及何时退出? @Matt 上游数据源负责发送 EOF。例如printf "" | catwhile read l; do true; done; echo finishing (第二种情况你必须手动输入 EOF/^D 才能通过) p.s. 请注意,如果您只输入例如cat 在命令行上,它将无限期地等待输入。在上面的例子中 printf 发送 EOF【参考方案5】:

取决于这里的目标:

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

也很有用。

【讨论】:

AFAIK,文件输入有一个缺点,限制 args 必须是文件名,但我的 args 可能是一些控制命令, 很公平!我试图处理“对一堆行做某事,可能来自标准输入”的常见习语:)【参考方案6】:

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

import sys
import select

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

在 Windows 上,选择模块只能与套接字一起使用,因此您需要使用替代机制。

【讨论】:

对不起,我必须删除接受,因为我使用 sys.stdin=cStringIO.StringIO("ddd") 将标准输入重定向到模拟文件,但它没有 fileno 方法,我使用你的代码,如果不是 select.select([sys.stdin],[],[],0.0)[0]: TypeError: argument must be an int, or have a fileno() method. @mlzboy:只有操作系统打开的“真实”文件才有文件描述符编号(顺便说一句,Unix 套接字或管道上的文件也是文件)。 select 调用操作系统的 select 函数只能使用这些文件。 StringIO 是一个只有 Python 解释器知道的虚拟文件,因此它没有文件描述符,你不能在上面使用 select @mlzboy 管道的缓冲区大小有限。写入没有读取任何内容的管道是危险的,因为如果您尝试写入超过缓冲区大小的内容,它将阻塞(死锁)。 在 cron 执行的脚本中使用此方法对我来说失败了。 sys.stdin.isatty() 但是在 cron 中确实为我工作。 在 Jenkins 中不起作用,返回 <_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'> 而不是 []

以上是关于如何检查标准输入是不是有一些数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查stdin是不是仍然打开而不阻塞?

如何在C中检查stdin是不是为空

从文件或标准输入读取

如何从标准输入读入数据--java语言

如何检查oracle监听是不是打开

如何在单个可执行文件中将数据重定向到标准输入?