如何检查标准输入是不是有一些数据?
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 "" | cat
或 while 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'>
而不是 []
以上是关于如何检查标准输入是不是有一些数据?的主要内容,如果未能解决你的问题,请参考以下文章