Reputation: 96927
I have a flag in my Python script which specifies whether I setup and use an external process or not. This process is a command called my_command
and it takes data from standard input. If I was to run this on the command-line, it would be something like:
$ my_command < data > result
I want to use a Python script to generate lines of data
by modifying standard input and feeding it to my_command
.
I'm doing something like this:
import getopt, sys, os, stat, subprocess
# for argument's sake, let's say this is set to True for now
# in real life, I use getopt.getopt() to decide whether this is True or False
useProcess = True
if useProcess:
process = subprocess.Popen(['my_command'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for line in sys.stdin:
# parse line from standard input and modify it
# we store the result in a variable called modified_line
modified_line = line + "foo"
# if we want to feed modified_line to my_command, do the following:
if useProcess:
process.stdin.write(modified_line)
# otherwise, we just print the modified line
else:
print modified_line
However, my_command
behaves as if it does not receive any data and quits with an error state. What am I doing wrong?
EDIT
Let's say my Python script is called my_Python_script
. Let's say I would normally pass my_command
a file called data
over standard input:
$ my_command < data > result
But now I'm passing it to my_Python_script
instead:
$ my_Python_script < data > some_other_result
I want my_Python_script
to conditionally set up a subprocess that runs my_command
on the contents of data
(which are modified by my_Python_script
before being passed to my_command
). Does this make more sense?
If I was using bash
as a scripting language, I would conditionally decide to run one of two functions. One would pipe lines of data to my_command
. The other would not. Can this be done with Python?
Upvotes: 9
Views: 5731
Reputation: 40688
After writing to the stdin, you need to close it:
process.stdin.write(modified_line)
process.stdin.close()
I failed to notice that the process.stdin.write()
was executed in a for loop. In which case, you should move the process.stdin.close()
to outside the loop.
Also, Raymond mentioned that we should call process.wait()
as well. So the updated code should be:
for ...
process.stdin.write(modified_line)
process.stdin.close()
process.wait()
Upvotes: 10
Reputation: 3469
In addition to process.stdin.close()
as mentioned by @HaiVu, did you do process.wait()
to wait for the command to finish before getting the result?
Upvotes: 3
Reputation: 2619
It seems like you may be confusing arguments and stdin. Your command should be
$ <data> | mycommand result
with data being passed in once the command is called.
Taking an input is done with the raw_input
builtin function. (http://docs.python.org/2/library/functions.html)
Upvotes: 0