Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute process in Python where data is written to stdin?

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?

like image 237
Alex Reynolds Avatar asked Mar 09 '13 00:03

Alex Reynolds


People also ask

Which method allows us to read data from the standard input stdin?

The readAll() method reads all remaining input on standard input and returns it as a string. As an example, the following code fragment reads all of the remaining tokens from standard input and returns them as an array of strings. String[] words = StdIn. readAllStrings();

How do I run a Python process?

How to Start a Process in Python? To start a new process, or in other words, a new subprocess in Python, you need to use the Popen function call. It is possible to pass two parameters in the function call. The first parameter is the program you want to start, and the second is the file argument.

What is SYS stdin read ()?

The sys. stdin is another way is to read from the standard input the calls input() function internally. Python has another module named fileinput for reading the standard input. The input() function of this module can be used to read standard input or read content from one or more files.


1 Answers

After writing to the stdin, you need to close it:

    process.stdin.write(modified_line)
    process.stdin.close()

Update

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()
like image 58
Hai Vu Avatar answered Sep 30 '22 17:09

Hai Vu