简体   繁体   中英

How do I accept piped input and then user-prompted input in a Python script?

I have a script that is designed to accept input piped in from stdin and then prompt the user for more input. Here is a contrived example illustrating what I mean:

import sys

# Get input from stdin
input_nums = [int(n.strip()) for n in sys.stdin]

# Prompt user
mult = int(raw_input("Enter a number by which to multiply your input: "))

for num in input_nums:
    print num*mult

When I pipe data in from stdin, python interprets stdin as closed before it gets to raw_input and it gives an EOFError: EOF when reading a line :

[user]$ cat nums.txt
2
3
4
5
[user]$ cat nums.txt | python sample.py
Enter a number by which to multiply your input: Traceback (most recent call last):
  File "sample.py", line 6, in <module>
    mult = int(raw_input("Enter a number by which to multiply your input: "))
EOFError: EOF when reading a line

(Please don't worry about the useless use of cat ... its just a minimal example)

What I want to know is if there is a way to somehow separate reading sys.stdin and calling raw_input so that I can both pipe in data and then prompt a user for input.

Updated to make it more clear what I really want by eliminating red herrings, and added traceback of EOFError

Result @TimPeter's solution worked for me, but I had to change "CON:" to "/dev/tty" since I'm on UNIX, not Windows.

I suspect you're out of luck, at least for any kind of cross-platform solution. Python uses sys.stdin for raw_input() , and if you invoke Python so that sys.stdin is on the receiving end of a pipe, Python can't do anything to magically change sys.stdin to the terminal when the piped input ends.

Here's a variant of the question with a Unix-specific workaround as the accepted answer. That cleverly worms around some (not all) of the problem by changing the way the program is invoked .

Sorry.

One way

This seems to work fine for Windows:

import sys
print len(sys.stdin.read()) # anything to consume piped input
sys.stdin = open("CON:", "r")
x = raw_input("sdfklj ")

That is, after reading the piped-in input, sys.stdin is rebound to the special file CON: (which is what Windows calls a DOS box) opened in read mode.

See your Unix docs for what to try there - perhaps /dev/tty1 ? There are mounds of terminal control options you may need to fiddle with too, depending on platform specifics. That's why I said (at the start) that I think you're out of luck for any cross-platform solution. Python has no special support for terminal devices; ie, you're on your own for that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM