How do I check if stdin has some data?

59,253

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.

Share:
59,253
mlzboy
Author by

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, 2022

Comments

  • mlzboy
    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
    mlzboy over 13 years
    i'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
    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 use select on it.
  • mlzboy
    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
    mlzboy over 13 years
    AFAIK,the fileinput has a disadvantge which limited the args must the filename,but my args may be some control command,
  • Sakie
    Sakie over 13 years
    Fair enough! I was trying to handle the common idiom of "do something to a bunch of lines, possibly from stdin" :)
  • Aryeh Leib Taurog
    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
    Niklas R over 9 years
    Thanks! This is so much easier than using select.
  • Alexx Roche
    Alexx Roche almost 9 years
    Thanks. That solved my: echo 'maybe pipe' | stdin.py +maybe_args on linux. Does melancholynaturegirl's solution work on windows?
  • Aaron
    Aaron almost 9 years
    so 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
    Lathan almost 9 years
    This 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
    Dave almost 8 years
    This 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
    GuySoft over 7 years
    Does not work in Jenkins, returns <_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'> and not []
  • ForceBru
    ForceBru about 7 years
    So, you're answering a question by referring to the very same question? WTF??
  • n.caillou
    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
    Matt almost 7 years
    What 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
    n.caillou almost 7 years
    @Matt the upstream data source is responsible for sending EOF. e.g. printf "" | cat or while read l; do true; done; echo finishing (in the second case you have to input EOF/^D manually to go through)
  • n.caillou
    n.caillou almost 7 years
    p.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
    ws_e_c421 about 6 years
    Since grep is mentioned in another post, I'll mention that less uses isatty. I came here looking to do something like less: 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
    Jeremy Friesner over 5 years
    Did you mean to say "because Windows doesn't allow it?" (Unix certainly does allow it)
  • n.caillou
    n.caillou over 5 years
    @JeremyFriesner Content may only become available after a while.
  • Jeremy Friesner
    Jeremy Friesner over 5 years
    @n.caillou certainly -- however, under Unix you can use select() (or poll() 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 have select() 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
    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
    andyn over 5 years
    This 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
    musiphil about 5 years
    This 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
    user almost 4 years
    I 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
    Nate Scarlet about 3 years
    fileinput.input is a function that not iterable, and this will block forever when no data
  • SmarthBansal
    SmarthBansal over 2 years
    But the program will wait for input and pause execution. You can't do something based on if stdin is empty.