(I think) I know how to read from a pipe. I mean calls on the bash like this
echo Bähm | ./script.py
This Python3 script work with that.
#!/usr/bin/env python3
import sys
x = sys.stdin.read()
if x:
print(x)
else:
print('no pipe')
sys.exit()
But when I simply do this on the bash
./script.py
nothing happens because it waits for input.
So I want to check (when starting the script) if there is input from a pipe or not. But I don't know why size
or len
didn't worked on sys.stdin
or sys.stdin.buffer
.
Maybe there is a difference in handling that between version 2 and 3 of Python, too?
Alternatively to @Cyrbil's answer if you really need to know if the input was piped in, you can use isatty
:
from sys import stdin
from os import isatty
is_pipe = not isatty(stdin.fileno())
You could use select, but it doesn't work on Windows:
import sys
import select
# Input: zero or more file-like objects
# Returns: list of objects that can be read
def can_read_files(*args):
return select.select(args, [], [], 0.0)[0]
if can_read_files(sys.stdin):
print(sys.stdin.read())
else:
print('No input')
To us it inline:
if select.select([sys.stdin], [], [], 0.0)[0]:
...
nothing happens because it waits for input
And that's completely fine. You want to fix something that doesn't need any fixing, and as a by-product you're actually creating problems.
Imagine a piping process that does some heavy calculations, and because of that, needs some time to produce the output. You cannot check for data availability in your python script. You don't know when the data is going to be available. You have to be patient.
So I want to check (when starting the script) if there is input from a pipe or not.
Don't. If, for some reason, your application hasn't meant to be run with a tty (waiting for user input), check for that.
sys.stdin.isatty()
Only check for data availability if there's some hard-time constraint: e.g.: the user has to respond within 2 seconds.
You can set the input entry file to non-blocking, and catching the IOError: [Errno 11] Resource temporarily unavailable
when nothing is piped.
import fcntl
import os
import sys
# make stdin a non-blocking file
fd = sys.stdin.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
try:
print(sys.stdin.read())
except:
print('No input')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With