What's the best way to tell if a Python program has anything to read from stdin?
Question:
I want a program to do one thing if executed like this:
cat something | my_program.py
and do another thing if run like this
my_program.py
But if I read from stdin, then it will wait for user input, so I want to see if there is anything to read before trying to read from stdin.
Answers:
I do not know the Python commands off the top of my head, but you should be able to do something with poll or select to look for data ready to read on standard input.
That might be Unix OS specific and different on Windows Python.
If you want to detect if someone is piping data into your program, or running it interactively you can use isatty to see if stdin is a terminal:
$ python -c 'import sys; print sys.stdin.isatty()'
True
$ echo | python -c 'import sys; print sys.stdin.isatty()'
False
Bad news. From a Unix command-line perspective those two invocations of your program are identical.
Unix can’t easily distinguish them. What you’re asking for isn’t really sensible, and you need to think of another way of using your program.
In the case where it’s not in a pipeline, what’s it supposed to read if it doesn’t read stdin?
Is it supposed to launch a GUI? If so, you might want to have a “-i” (–interactive) option to indicate you want a GUI, not reading of stdin.
You can, sometimes, distinguish pipes from the console because the console device is “/dev/tty”, but this is not portable.
You want the select module (man select
on unix) It will allow you to test if there is anything readable on stdin. Note that select won’t work on Window with file objects. But from your pipe-laden question I’m assuming you’re on a unix based os 🙂
http://docs.python.org/library/select.html
root::2832 jobs:0 [~] # cat stdin_test.py
#!/usr/bin/env python
import sys
import select
r, w, x = select.select([sys.stdin], [], [], 0)
if r:
print "READABLES:", r
else:
print "no pipe"
root::2832 jobs:0 [~] # ./stdin_test.py
no pipe
root::2832 jobs:0 [~] # echo "foo" | ./stdin_test.py
READABLES: [<open file '<stdin>', mode 'r' at 0xb7d79020>]
I want a program to do one thing if executed like this:
cat something | my_program.py
and do another thing if run like this
my_program.py
But if I read from stdin, then it will wait for user input, so I want to see if there is anything to read before trying to read from stdin.
I do not know the Python commands off the top of my head, but you should be able to do something with poll or select to look for data ready to read on standard input.
That might be Unix OS specific and different on Windows Python.
If you want to detect if someone is piping data into your program, or running it interactively you can use isatty to see if stdin is a terminal:
$ python -c 'import sys; print sys.stdin.isatty()'
True
$ echo | python -c 'import sys; print sys.stdin.isatty()'
False
Bad news. From a Unix command-line perspective those two invocations of your program are identical.
Unix can’t easily distinguish them. What you’re asking for isn’t really sensible, and you need to think of another way of using your program.
In the case where it’s not in a pipeline, what’s it supposed to read if it doesn’t read stdin?
Is it supposed to launch a GUI? If so, you might want to have a “-i” (–interactive) option to indicate you want a GUI, not reading of stdin.
You can, sometimes, distinguish pipes from the console because the console device is “/dev/tty”, but this is not portable.
You want the select module (man select
on unix) It will allow you to test if there is anything readable on stdin. Note that select won’t work on Window with file objects. But from your pipe-laden question I’m assuming you’re on a unix based os 🙂
http://docs.python.org/library/select.html
root::2832 jobs:0 [~] # cat stdin_test.py
#!/usr/bin/env python
import sys
import select
r, w, x = select.select([sys.stdin], [], [], 0)
if r:
print "READABLES:", r
else:
print "no pipe"
root::2832 jobs:0 [~] # ./stdin_test.py
no pipe
root::2832 jobs:0 [~] # echo "foo" | ./stdin_test.py
READABLES: [<open file '<stdin>', mode 'r' at 0xb7d79020>]