title: piping with error checking using subprocess in python
body: <p>I have a piping scheme using <code>subprocess</code> where one process <code>p2</code> takes the output of another process <code>p1</code> as input:</p>
  
  <pre><code>p1 = subprocess.Popen("ls -al", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  p2 = subprocess.Popen("grep mytext - ", shell=True, stdin=p1.stdout, stdout=subprocess.PIPE)
  result = p2.communicate()
  </code></pre>
  
  <p><code>p1</code> or <code>p2</code> could fail for various reasons, like wrong inputs or malformed commands. </p>
  
  <p>This code works fine when <code>p1</code> does not fail. How can I do this but also check whether <code>p1</code> specifically or <code>p2</code> specifically failed? Example:</p>
  
  <pre><code># p1 will fail since notafile does not exist
  p1 = subprocess.Popen("ls notafile", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  p2 = subprocess.Popen("grep mytext - ", shell=True, stdin=p1.stdout, stdout=subprocess.PIPE)
  result = p2.communicate()
  </code></pre>
  
  <p>I can check <code>p2.returncode</code> and see that it's not <code>0</code>, but that could mean that <code>p2</code> failed or p1 failed. How can I specifically check whether <code>p1</code> failed or <code>p2</code> failed in cases where this pipe goes wrong? </p>
  
  <p>I don't see how I can use <code>p1.returncode</code> for this which would be the ideal and obvious solution. ex:</p>
  
  <pre><code>p1 = subprocess.Popen("ls foo", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  p2 = subprocess.Popen("grep mytext - ", shell=True, stdin=p1.stdout, stdout=subprocess.PIPE)
  # here, p2.returncode not defined yet since we didn't communicate()
  assert(p2 is None)
  r = p2.communicate()
  # now p2 has a returncode
  assert(p2.returncode is not None)
  # ... but p1 does not!
  assert(p1.returncode is None)
  </code></pre>
  
  <p>so I don't see how returncode helps here?</p>
  
  <p>The full solution thanks to @abarnert is something like this:</p>
  
  <pre><code>p1 = subprocess.Popen("ls -al", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  p2 = subprocess.Popen("grep mytext - ", shell=True, stdin=p1.stdout, stdout=subprocess.PIPE)
  result = p2.communicate()
  if p2.returncode != 0:
    # something failed
    if p1.wait() != 0:
       # p1 failed...
    else: 
       # p2 failed...
  </code></pre>
  
  <p>p.s. I know the caveats of <code>shell=True</code> for security.</p>