1

I am using Python to script running an exe program. If we open the exe program in the shell, we could enter different command such as "a", "b", "c" in the program. These commands can not be passed as flags into the exe program. I want to use Python to script running this exe program for many times, with custom exe-program specific input. But if I run the "program.exe" with

p = subprocess.call(['program.exe'],
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     )

Python won't terminate. Can I achieve this purpose with subprocess in Python?

martineau
  • 119,623
  • 25
  • 170
  • 301
keli95566
  • 21
  • 5
  • https://stackoverflow.com/questions/29060281/interact-with-standard-input-output-of-another-process, https://stackoverflow.com/questions/10673185/python-execute-command-line-sending-input-and-reading-output – AMC Feb 11 '20 at 20:24

2 Answers2

2

First, you have to use p = subprocess.Popen(…) in order to get the subprocess object. subprocess.call(…) would give you just the return status, and that's not enough.

If p is your connection object, you can send your commands to p.stdin, such as p.stdin.write("a\n"), and then read out p.stdout() until the next indication that the command output is finished. How you detect this depends on said program.

Then you can send the next command and read its output.

At the end, you can do p.stdin.close() in order to signal an EOF ot the other process, and then it should terminate.

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • Thank you for helping me. The second method works, but for some reason I also had to set `bufsize=0` and shell=True` . – keli95566 Feb 11 '20 at 14:41
2

Beware: subprocess.call will not return before the child process has terminated. So you have no possibility to write anything to the standard input of the child.

If you can prepare the bunch of commands in advance, and if output has no risk to fill the system buffer, you can still use call that way:

cmds = "a\nb\nc\n"

p = subprocess.call(['program.exe'],
                     stdin=io.StringIO(cmds),
                     stdout=subprocess.PIPE,
                     )

But the more robust way is to directly use the Popen constructor, and then feed the input:

p = subprocess.Popen(['program.exe'],
                 stdin=subprocess.PIPE,
                 stdout=subprocess.PIPE,
                 )
p.stdin.write("a\n");
p.stdin.write("b\n");
...
p.stdin.close();
p.wait();

If you know that one subcommand will generate very large output you can read it before sending the next one. Beware to avoid being blocked waiting an input that the child has still not sent...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Hi Serge, thank you for helping me. The second method works, but for some reason I also had to set `bufsize=0` and ` shell=True` . – keli95566 Feb 11 '20 at 14:41