Search code examples
python-3.xsubprocessinfinite-loopcommunicationpopen

Circle Piping to and from 2 Python Subprocesses


I needed help regarding the subprocess module. This question might sound repeated, and I have seen a number of articles related to it in a number of ways. But even so I am unable to solve my problem. It goes as follows:
I have a C program 2.c it's contents are as follows:

#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
while(1)
  {
   if(a==0)               //Specific case for the first input
     {
      printf("%d\n",(a+1));
      break;
     }
   scanf("%d",&a);
   printf("%d\n",a);
  }
return 0;
}

I need to write a python script which first compiles the code using subprocess.call() and then opens two process using Popen to execute the respective C-program. Now the output of the first process must be the input of the second and vice versa. So essentially, if my initial input was 0, then the first process outputs 2, which is taken by second process. It in turn outputs 3 and so on infinitely.

The below script is what I had in mind, but it is flawed. If someone can help me I would very much appreciate it.

from subprocess import *
call(["gcc","2.c"])
a = Popen(["./a.out"],stdin=PIPE,stdout=PIPE) #Initiating Process
a.stdin.write('0')
temp = a.communicate()[0]
print temp
b = Popen(["./a.out"],stdin=PIPE,stdout=PIPE) #The 2 processes in question
c = Popen(["./a.out"],stdin=PIPE,stdout=PIPE)
while True:
    b.stdin.write(str(temp))
    temp = b.communicate()[0]
    print temp
    c.stdin.write(str(temp))
    temp = c.communicate()[0]
    print temp
a.wait()
b.wait()
c.wait()

Solution

  • Problem is here

    while True:
        b.stdin.write(str(temp))
        temp = b.communicate()[0]
        print temp
        c.stdin.write(str(temp))
        temp = c.communicate()[0]
        print temp
    

    Once communicate has returned, it does noting more. You have to run the process again. Plus you don't need 2 processes open at the same time.

    Plus the init phase is not different from the running phase, except that you provide the input data.

    what you could do to simplify and make it work:

    from subprocess import *
    call(["gcc","2.c"])
    temp = str(0)
    
    while True:
        b = Popen(["./a.out"],stdin=PIPE,stdout=PIPE) #The 2 processes in question
        b.stdin.write(temp)
        temp = b.communicate()[0]
        print temp
        b.wait()
    

    Else, to see 2 processes running in parallel, proving that you can do that, just fix your loop as follows (by moving the Popen calls in the loop):

    while True:
    
        b = Popen(["./a.out"],stdin=PIPE,stdout=PIPE) #The 2 processes in question
        c = Popen(["./a.out"],stdin=PIPE,stdout=PIPE)
    
        b.stdin.write(str(temp))
        temp = b.communicate()[0]
        print temp
        c.stdin.write(str(temp))
        temp = c.communicate()[0]
        print temp
    

    better yet. b output feeds c input:

    while True:
    
        b = Popen(["./a.out"],stdin=PIPE,stdout=PIPE) #The 2 processes in question
        c = Popen(["./a.out"],stdin=b.stdout,stdout=PIPE)
    
        b.stdin.write(str(temp))
        temp = c.communicate()[0]
        print temp