Is it possible to combine piped input and TTY prompts in Python CLI scripts? E.g., running this:
import sys
piped_text = None
if not sys.stdin.isatty():
piped_text = sys.stdin.read()
user_in = raw_input('Enter something: ')
if piped_text:
sys.stdout.write(piped_text)
sys.stdout.write(user_in + '\n')
Produces the following output:
~: python mrprompt.py
Enter something: something
something
~: echo foo | python mrprompt.py
Enter something: Traceback (most recent call last):
File "mrprompt.py", line 9, in <module>
user_in = raw_input('Enter something: ')
EOFError: EOF when reading a line
When the output I'm looking for is this:
~: python mrprompt.py
Enter something: something
something
~: echo foo | python mrprompt.py
Enter something: something
foo
something
I guess, worded differently, is it possible for a subshell to know the tty of its parent shell? Is it possible, in Python, to interact a parent shell's tty? I use bash inside of GNU Screen (therefore, reading the 'SSH_TTY' environment variable is not a viable option).
This works, more or less:
#!/usr/bin/python
import sys
saved_stdin = sys.stdin
sys.stdin = open('/dev/tty', 'r')
result = raw_input('Enter something: ')
sys.stdout.write('Got: ' + result + '\n')
sys.stdin = saved_stdin
result2 = sys.stdin.read()
sys.stdout.write('Also got: ' + result2)
Save as foo.py
and try echo goodbye | ./foo.py
Of course, /dev/tty
only exists on Unix. And if you run it in a process with no controlling terminal, the open()
will probably fail...
You can detect whether or not your stdin
is coming from a pipe, as you are with sys.stdin.isatty
. You're getting the EOF
because you read all the input from with the stdin.read()
and then you try to read some more with the raw_input()
command.
What you can't do is both pipe input and do inter-active input. If you're piping input in, there is no other stdin
for raw_input
to work against. The only stdin
is the one coming from the file.
What you need to do is offer an optional way to have the appropriate part of your script read input from a file, with a switch like
--input=file.txt
and then provide interactive prompts for the other parts.
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