質問

I am using:

grepOut = subprocess.check_output("grep " + search + " tmp", shell=True)

To run a terminal command, I know that I can use a try/except to catch the error but how can I get the value of the error code?

I found this on the official documentation:

 exception subprocess.CalledProcessError

    Exception raised when a process run by check_call() or check_output() returns a non-zero exit status.

    returncode

        Exit status of the child process.

But there are no examples given and Google was of no help.

役に立ちましたか?

解決

You can get the error code and results from the exception that is raised.

This can be done through the fields returncode and output.

For example:

import subprocess

try:
    grepOut = subprocess.check_output("grep " + "test" + " tmp", shell=True)                       
except subprocess.CalledProcessError as grepexc:                                                                                                   
    print("error code", grepexc.returncode, grepexc.output)

他のヒント

Python 3.5 introduced the subprocess.run() method. The signature looks like:

subprocess.run(
  args, 
  *, 
  stdin=None, 
  input=None, 
  stdout=None, 
  stderr=None, 
  shell=False, 
  timeout=None, 
  check=False
)

The returned result is a subprocess.CompletedProcess. In 3.5, you can access the args, returncode, stdout, and stderr from the executed process.

Example:

>>> result = subprocess.run(['ls', '/tmp'], stdout=subprocess.DEVNULL)
>>> result.returncode
0

>>> result = subprocess.run(['ls', '/nonexistent'], stderr=subprocess.DEVNULL)
>>> result.returncode
2

is there a way to get a return code without a try/except?

check_output raises an exception if it receives non-zero exit status because it frequently means that a command failed. grep may return non-zero exit status even if there is no error -- you could use .communicate() in this case:

from subprocess import Popen, PIPE

pattern, filename = 'test', 'tmp'
p = Popen(['grep', pattern, filename], stdin=PIPE, stdout=PIPE, stderr=PIPE,
          bufsize=-1)
output, error = p.communicate()
if p.returncode == 0:
   print('%r is found in %s: %r' % (pattern, filename, output))
elif p.returncode == 1:
   print('%r is NOT found in %s: %r' % (pattern, filename, output))
else:
   assert p.returncode > 1
   print('error occurred: %r' % (error,))

You don't need to call an external command to filter lines, you could do it in pure Python:

with open('tmp') as file:
    for line in file:
        if 'test' in line:
            print line,

If you don't need the output; you could use subprocess.call():

import os
from subprocess import call
try:
    from subprocess import DEVNULL # Python 3
except ImportError: # Python 2
    DEVNULL = open(os.devnull, 'r+b', 0)

returncode = call(['grep', 'test', 'tmp'], 
                  stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)

To get both output and return code (without try/except) simply use subprocess.getstatusoutput (Python 3 required)

In Python 2 - use commands module:

import command
rc, out = commands.getstatusoutput("ls missing-file")
if rc != 0: print "Error occurred: %s" % out

In Python 3 - use subprocess module:

import subprocess
rc, out = subprocess.getstatusoutput("ls missing-file")
if rc != 0: print ("Error occurred:", out)

Error occurred: ls: cannot access missing-file: No such file or directory

Note that since Python 3.5 it is better to use subprocess.run() :

import subprocess

grepOut = subprocess.run(['grep', search, 'tmp'], shell=True) ## Only use shell=True if necessary

This will generate a subprocess.CompletedProcess instance which will be stored at grepOut. Then, and finally answering your question, you can get the return value from subprocess.run() like this:

grepOut.returncode

which will be equal to 0 if the command was successful, and not equal to 0 if it failed.

Finally, for completeness sake, you could even handle the error by means of a try/except block using the method check_returncode() from subprocess.CompletedProcess class:

try:
    ## Add argument `capture_output=True` if you want to store the output of the command
    grepOut = subprocess.run(['grep', search, 'tmp'], shell=True)
    grepOut.check_returncode()

except subprocess.CalledProcessError as err:
    ## If returncode is non-zero, raise a CalledProcessError and print this message
    print(f"Oops, something went wrong. Error code: {err.returncode}")

Hope it is clear enough.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top