Question

Why does communicate kill my process? I want an interactive process but communicate does something so that I cannot take raw_input any more in my process.

from sys import stdin 
from threading import Thread
from time import sleep

if __name__ == '__main__':
    print("Still Running\n")
    x = raw_input()    
    i = 0
    while ('n' not in x ) :
        print("Still Running " + str(i) + " \r\n")
        x = raw_input()
        i += 1

    print("quit")



print(aSubProc.theProcess.communicate('y'))
print(aSubProc.theProcess.communicate('y'))

exception!

self.stdin.write(input)
ValueError: I/O operation on closed file
Was it helpful?

Solution

communicate and wait methods of Popen objects, close the PIPE after the process returns. If you want stay in communication with the process try something like this:

import subprocess
proc = subprocess.Popen("some_process", stdout=subprocess.PIPE, stdin=subprocess.PIPE)
proc.stdin.write("input")
proc.stdout.readline()

OTHER TIPS

Why does communicate kill my process?

From the docs for Popen.communicate(input=None, timeout=None):

Interact with process: Send data to stdin. Read data from stdout and
stderr, until end-of-file is reached. Wait for process to terminate. emphasize mine

You may call .communicate() only once. It means that you should provide all input at once:

#!/usr/bin/env python
import os
import sys
from subprocess import Popen, PIPE

p = Popen([sys.executable, 'child.py'], stdin=PIPE, stdout=PIPE)
print p.communicate(os.linesep.join('yyn'))[0]

Output

Still Running

Still Running 0 

Still Running 1 

quit

Notice the doubled newlines: one from '\r\n' and another from print statement itself in your script for the child process.

Output shows that the child process received three input lines successfully ('y', 'y', and 'n').

Here's a similar code using subprocess.check_output()'s input parameter from Python3.4:

#!/usr/bin/env python3.4
import os
import sys
from subprocess import check_output

output = check_output(['python2', 'child.py'], universal_newlines=True,
                      input='\n'.join('yyn'))
print(output, end='')

It produces the same output.


If you want to provide a different input depending on responses from the child processes then use pexpect module or its analogs to avoid issues mentioned in Why not just use a pipe (popen())?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top