'IPython - pipe multiple subprocesses and show result of final one to stdout

There are a lot of questions related to this one but none seems to work for my case: 1-https://stackoverflow.com/questions/9655841/python-subprocess-how-to-use-pipes-thrice?noredirect=1&lq=1 2-https://stackoverflow.com/questions/295459/how-do-i-use-subprocess-popen-to-connect-multiple-processes-by-pipes?noredirect=1&lq=1 3-https://stackoverflow.com/questions/6062340/python-subprocess-output-to-stdout 4-https://stackoverflow.com/questions/13332268/how-to-use-subprocess-command-with-pipes?noredirect=1&lq=1 5-https://stackoverflow.com/questions/6062340/python-subprocess-output-to-stdout

What I am trying to accomplish is something equivalent to ./my_executable | rev | rev (I realise this ends up being the same as just ./my_executable, however I need to do it like this), but using IPython.

I'm running the following series of commands:

p1 = subprocess.Popen("rev", stdin=subprocess.PIPE)
p2 = subprocess.Popen("rev", stdout=p1.stdin, stdin=subprocess.PIPE) 
subprocess.Popen("my_executable", stdout=p2.stdin)

And am not getting any output.

Since I am not specifying any argument for p1.stdout I would assume it would output to the terminal where I'm running IPython. In fact, if I just do

p1 = subprocess.Popen("rev", stdin=subprocess.PIPE)
subprocess.Popen("my_executable", stdout=p1.stdin)

it will output to the terminal.

Because of this, I thought there was some problem with my pipe from p2 to p1. However, when I run the following series of commands

f = open("test", "w")
p1 = subprocess.Popen("rev", stdout=f, stdin=subprocess.PIPE)
p2 = subprocess.Popen("rev", stdout=p1.stdin, stdin=subprocess.PIPE) 
subprocess.Popen("my_executable", stdout=p2.stdin)
f.close()

And then do cat test in the terminal everything works fine, so it seems like I'm using pipes correctly.

Why does the first example not output to the terminal?



Solution 1:[1]

The solution I found is to close the stdin of the process:

p1 = subprocess.Popen("rev", stdin=subprocess.PIPE)
p2 = subprocess.Popen("rev", stdout=p1.stdin, stdin=subprocess.PIPE) 
subprocess.Popen("my_executable", stdout=p2.stdin)
p2.stdin.close()

After closing the stdin p1 will output its stdout.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 chilliefiber