I see this code snippet referenced quite a lot during discussions around Python subprocess pipelines. Obligatory link: https://docs.python.org/3.4/library/subprocess.html#replacing-shell-pipeline
Modified slightly:
p1 = subprocess.Popen(['cat'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
p2 = subprocess.Popen(['head', '-n', '1'],
stdin=p1.stdout,
stdout=subprocess.PIPE)
# Allow p1 to receive a SIGPIPE if p2 exits.
p1.stdout.close()
output = p2.communicate()[0]
This shell pipeline is pointless, except to succinctly demonstrate the challenge. Input "abc\ndef\nghi\n"
and only "abc\n"
should be captured in output
.
What is the best way to write data to p1.stdin
? I am aware of the input
argument to subprocess.Popen.communicate()
, but it won't work in a pipeline. Also, the solution needs to handling blocking correctly.
My guess: Reverse engineer the code behind communicate()
and create another version for this specific issue. Before I do that, I want to ask if there is a simpler solution of which I am not aware.
You need to call an equivalent of
p1.communicate(b"abc\ndef\nghi\n")
andoutput = p2.communicate()[0]
concurrently. A portable way to do it is to use threads orasyncio
.