Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get exit code from subprocess.Popen?

Tags:

python

With the code below, p.returncode is always None. According to the Popen.returncode documentation, this means that the process hasn't finished yet.

Why am I not getting an exit code?

import os
import sys
import subprocess

cmd = ['echo','hello']
p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)
try:
    # Filter stdout
    for line in iter(p.stdout.readline, ''):
        sys.stdout.flush()
        # Print status
        print(">>> " + line.rstrip())
        sys.stdout.flush()
except:
    sys.stdout.flush()

print 'RETURN CODE', p.returncode

Please note: The reason why I'm reading each line separately is because I want to filter the output of other, long-running, processes in real-time and halt them based on certain strings.

I'm on Python 2.7.5 (CentOS 7 64-bit).


Solution

Thanks to the answer posted by @skyking, I can now successfully capture the exit code like this, using Popen.poll() (Popen.wait() deadlocked my process):

import os
import sys
import subprocess
import time

cmd = ['echo','hello']
p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)
try:
    # Filter stdout
    for line in iter(p.stdout.readline, ''):
        sys.stdout.flush()
        # Print status
        print(">>> " + line.rstrip())
        sys.stdout.flush()
except:
    sys.stdout.flush()

# Wait until process terminates (without using p.wait())
while p.poll() is None:
    # Process hasn't exited yet, let's wait some
    time.sleep(0.5)

# Get return code from process
return_code = p.returncode

print 'RETURN CODE', return_code

# Exit with return code from process
sys.exit(return_code)
like image 640
fredrik Avatar asked Apr 13 '16 11:04

fredrik


People also ask

How do I get the exit code in Python?

You can set an exit code for a process via sys. exit() and retrieve the exit code via the exitcode attribute on the multiprocessing.

What does subprocess Popen return?

Popen Function The function should return a pointer to a stream that may be used to read from or write to the pipe while also creating a pipe between the calling application and the executed command. Immediately after starting, the Popen function returns data, and it does not wait for the subprocess to finish.

Does subprocess Popen wait for completion?

Save this answer. Try subprocess. call instead of Popen. It waits for the command to complete.


1 Answers

According to the linked to documentation

The child return code, set by poll() and wait() (and indirectly by communicate()). A None value indicates that the process hasn’t terminated yet.

A negative value -N indicates that the child was terminated by signal N (Unix only).

You have not called poll or wait so returncode won't be set.

On the other hand if you look in to the source code for fx check_output you see that they are directly using the return value from poll to examine the return code. They know that the process has terminated at that point because they have called wait earlier. If you don't know that you would have to call the wait method instead (but note the deadlock possibility noted in the documentation).

Normally the program will have terminated when you've read all of stdout/stderr, but that's not guaranteed and that may be what you're seeing. Either the program or the OS can close stdout (and stderr) before the process actually terminates and then by just calling poll immediately after you've read all the output from the program might fail.

like image 50
skyking Avatar answered Oct 10 '22 18:10

skyking