How do I check if stdin has some data?
Solution 1
On Unix systems you can do the following:
import sys
import select
if select.select([sys.stdin, ], [], [], 0.0)[0]:
print("Have data!")
else:
print("No data")
On Windows the select module may only be used with sockets though so you'd need to use an alternative mechanism.
Solution 2
I've been using
if not sys.stdin.isatty()
Here's an example:
import sys
def main():
if not sys.stdin.isatty():
print "not sys.stdin.isatty"
else:
print "is sys.stdin.isatty"
Running
$ echo "asdf" | stdin.py
not sys.stdin.isatty
sys.stdin.isatty()
returns false if stdin
is not connected to an interactive input device (e.g. a tty).
isatty(...)
isatty() -> true or false. True if the file is connected to a tty device.
Solution 3
As mentioned by others, there's no foolproof way to know if data will become available from stdin, because UNIX doesn't allow it (and more generally because it can't guess the future behavior of whatever program stdin connects to).
Always wait for stdin, even if there may be nothing (that's what grep
etc. do), or ask the user for a -
argument.
Solution 4
Depending on the goal here:
import fileinput
for line in fileinput.input():
do_something(line)
can also be useful.
mlzboy
i'm a python freelancer,currently living in YiWu zhengjiang province,china before i use ubuntu & python,i have experience on html,ajax,.net,java,asp etc, now i'm a totally ubuntu & python fan. you can visit my tech blog on http://lexus.cnblogs.com currently i maintence a eCommerical search engine http://www.15-1688.com
Updated on July 05, 2022Comments
-
mlzboy almost 2 years
In Python, how do you check if
sys.stdin
has data or not?I found that
os.isatty(0)
can not only check if stdin is connected to a TTY device, but also if there is data available.But if someone uses code such as
sys.stdin = cStringIO.StringIO("ddd")
and after that uses
os.isatty(0)
, it still returns True. What do I need to do to check if stdin has data? -
mlzboy over 13 yearsi'm sorry i have to remove the accept,because i use sys.stdin=cStringIO.StringIO("ddd") redirect the stdin to a mock file,but it didn't have fileno method,it i use you code it will raise if not select.select([sys.stdin],[],[],0.0)[0]: TypeError: argument must be an int, or have a fileno() method.
-
Cristian Ciupitu over 13 years@mlzboy: only "real" files, opened by the operating system have a file descriptor number (btw on Unix sockets or pipes are files too).
select
which calls the operating system's select function can work only with those files.StringIO
is a virtual file known only to the Python interpreter therefore it doesn't have a file descriptor and you can't useselect
on it. -
mlzboy over 13 years@Cristian Ciupitu thank you i got it,finally i use pipe replace StringIO,here is the code,may be help others r="\n".join(dict["list_result"].split("\n")[:i]) fdr,fdw=os.pipe() os.write(fdw,r) os.close(fdw) f=os.fdopen(fdr) sys.stdin=f
-
mlzboy over 13 yearsAFAIK,the fileinput has a disadvantge which limited the args must the filename,but my args may be some control command,
-
Sakie over 13 yearsFair enough! I was trying to handle the common idiom of "do something to a bunch of lines, possibly from stdin" :)
-
Aryeh Leib Taurog almost 10 years@mlzboy pipes have a limited buffer size. Writing to a pipe with nothing reading from it is dangerous because if you try to write more than the buffer size it will block (deadlock).
-
Niklas R over 9 yearsThanks! This is so much easier than using
select
. -
Alexx Roche almost 9 yearsThanks. That solved my: echo 'maybe pipe' | stdin.py +maybe_args on linux. Does melancholynaturegirl's solution work on windows?
-
Aaron almost 9 yearsso it seems... C:\Users\naturegirl\Desktop>C:\Python27\python.exe isatty.py is sys.stdin.isatty C:\Users\naturegirl\Desktop> C:\Users\naturegirl\Desktop>echo "foo" | C:\Python27\python.exe isatty.py not sys.stdin.isatty
-
Lathan almost 9 yearsThis is not a good idea. What if stdin is being piped in from a file? isatty() is telling you if stdin is coming in directly from a terminal, not if there is more data to read from stdin
-
Dave almost 8 yearsThis method failed for me when used in a script that was executed by cron.
sys.stdin.isatty()
however did work for me within cron. -
GuySoft over 7 yearsDoes not work in Jenkins, returns
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
and not[]
-
ForceBru about 7 yearsSo, you're answering a question by referring to the very same question? WTF??
-
n.caillou about 7 years@ForceBru This is indeed very confusing, haha. It would seem that another question was merged here. I have edited.
-
Matt almost 7 yearsWhat would the process be - wait for stdin and read until an EOF, then process the data? That is, how do grep et al. know when to process data and when to quit?
-
n.caillou almost 7 years@Matt the upstream data source is responsible for sending EOF. e.g.
printf "" | cat
orwhile read l; do true; done; echo finishing
(in the second case you have to input EOF/^D manually to go through) -
n.caillou almost 7 yearsp.s. Note that if you enter just e.g.
cat
on the command line, it will wait for input indefinitely. In the above example printf sends EOF -
ws_e_c421 about 6 yearsSince
grep
is mentioned in another post, I'll mention thatless
usesisatty
. I came here looking to do something likeless
: read input from a file if a file path is given as an input argument, but read input from stdin otherwise. An alternative is to use-
as an alias for stdin and just accept the file argument. -
Jeremy Friesner over 5 yearsDid you mean to say "because Windows doesn't allow it?" (Unix certainly does allow it)
-
n.caillou over 5 years@JeremyFriesner Content may only become available after a while.
-
Jeremy Friesner over 5 years@n.caillou certainly -- however, under Unix you can use
select()
(orpoll()
or etc) to find out if there is data to read on stdin. You can do it either as an instantaneous-poll (by setting the timeout parameter to 0), or you can haveselect()
block until data is ready, and then return. On Unix-based OS's, STDIN_FILENO behaves more or less the same as any other socket or file descriptor (whereas on Windows, you're mostly out-of-luck -- your only option is to work-around the problem by spawning a separate thread to read from stdin and pass the data back to the main thread via a socket) -
n.caillou over 5 years@JeremyFriesner Actually, I think this is another byproduct of the merging mentioned in another comment. The context for my answer has gone missing; I'll try to clarify it. We agree that UNIX lets you know if there is anything in stdin at the moment, and if stdin is connected to a terminal.
-
andyn over 5 yearsThis is dangerous. If the script is run with
/dev/null
as stdin, select.select will immediately return. This is the case when running the script via cron or other tools. The easiest way to replicate this behavior is to add< /dev/null
on the command line. -
musiphil about 5 yearsThis method tests only whether
sys.stdin
has data that are immediately available. And I don't think that is strictly guaranteed even when it is connected to a file (e.g. what if it is connected to a file on an NFS and the underlying network connection is spotty?).select
is meant for multiplexing, i.e. choosing whatever is ready to read/write from multiple sources/destinations. -
user almost 4 yearsI think this answers whether the input comes from a "human typing on a terminal who will then press Ctrl+D to send the input" or some "data stream" (stdin from pipe, file, etc.), whereas the other post with
select
answers whether the "data stream" has any more data in it. -
Nate Scarlet about 3 years
fileinput.input
is a function that not iterable, and this will block forever when no data -
SmarthBansal over 2 yearsBut the program will wait for input and pause execution. You can't do something based on if stdin is empty.