Ignoring CalledProcessError
Asked Answered
P

3

18

I am using the subprocess module and check_output() to create a virtual shell in my Python script, and it works fine for commands that return a zero exit status, however for ones that don't it returns an exception without printing the error that would have been displayed in the output on a normal shell.

For instance, I would expect something to work like this:

>>> shell('cat non-existing-file')
cat: non-existing-file: No such file or directory

But instead, this happens:

>>> shell('cat non-existing-file')
CalledProcessError: Command 'cat non-existing-file' returned non-zero exit status 1 (file "/usr/lib/python2.7/subprocess.py", line 544, in check_output)

Even though I could remove the Python exception message using try and except, I still want the cat: non-existing-file: No such file or directory to display to the user.

How would I go about doing this?

shell():

def shell(command):
    output   = subprocess.check_output(command, shell=True)
    finished = output.split('\n')

    for line in finished:
      print line
    return
Pressman answered 18/8, 2012 at 4:10 Comment(0)
M
21

Something like this perhaps?

def shell(command):
    try:
        output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
    except Exception, e:
        output = str(e.output)
    finished = output.split('\n')
    for line in finished:
        print line
    return
Matchlock answered 18/8, 2012 at 4:32 Comment(9)
How would I convert the Popen object to a string? It's not working here with str(): <subprocess.Popen object at 0x12a4f90>Pressman
You can use the __str__() method. For example output.__str__()Matchlock
Hm.. did you try the code I just edited in the initial answer?Matchlock
Yeah. It seems to actually print the expected output on the terminal where the script is running from, but for where I set it to print (it doesn't actually print, it uses another function for an IRC bot to talk in a channel) it displays the <subprocess.Popen object at 0x12a4f90>. Not sure what to do about that.Pressman
UPDATE: even though the previous code worked, the try-except version may be more to your liking, as it does not give the <subprocess.Popen ... > messageMatchlock
Well, now the output it gives is Command 'cat nope' returned non-zero exit status 1, I'd like the error the shell would have given instead of the Python exception message.Pressman
let us continue this discussion in chatMatchlock
python 3, I replace exception capture code: "except subprocess.CalledProcessError as e:" and it worksRoubaix
There should be an option in subprocess to ignore errors like this.Sato
A
3

If you're using Python 3.5+, you can run it with check=False:

subprocess.run("exit 1", shell=True, check=False)

If check is true, and the process exits with a non-zero exit code, a CalledProcessError exception will be raised. Attributes of that exception hold the arguments, the exit code, and stdout and stderr if they were captured.

For older Python 3 versions, there's different methods for checking vs not checking the call.

To get the output, just pass capture_output=True and then get stdout value from CompletedProcess

Apteral answered 7/6, 2023 at 14:3 Comment(0)
H
0

How about using subprocess.run()

import subprocess
output = subprocess.run(['cat', 'non-existing-file'], stdout = subprocess.PIPE, stderr=subprocess.PIPE)
print (output.stderr.decode())

Here is the output

> python3 file.py
cat: non-existing-file: No such file or directory
Hellas answered 11/3, 2024 at 9:51 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.