py_works
py_works

Reputation: 190

how to capture subprocess error

In Python, I run an exe made using FORTRAN. I use the subprocess module. that exe accesses and writes to several files. If I make those files readonly, I see the following trace in my Python console.

I tried by using try, except statements. But I could not capture the error. I also tried using p.stdout.readline(). But was unsuccessful.

Is there a systematic way to capture this sort of errors.

Code:

import subprocess
p = subprocess.Popen('C:\\TGSSR\\test.exe' , shell=True, stdout=subprocess.PIPE)

Traceback:

forrtl: severe (9): permission to access file denied, unit 6, file C:\test\mar22_SSOUT\RawReadLog.dat

Image              PC        Routine            Line        Source             
test.exe           0116DC40  Unknown               Unknown  Unknown
test.exe           0113D42F  Unknown               Unknown  Unknown
test.exe           0112AE97  Unknown               Unknown  Unknown
test.exe           0112A1DA  Unknown               Unknown  Unknown
test.exe           0110D746  Unknown               Unknown  Unknown
test.exe           0108B9AC  Unknown               Unknown  Unknown
test.exe           01173FE3  Unknown               Unknown  Unknown
test.exe           011588F5  Unknown               Unknown  Unknown
kernel32.dll       76D33677  Unknown               Unknown  Unknown
ntdll.dll          77A39F42  Unknown               Unknown  Unknown
ntdll.dll          77A39F15  Unknown               Unknown  Unknown

Upvotes: 5

Views: 25470

Answers (4)

In the majority of cases, you need to use subprocess.run. And to capture the error, you have to use the parameter "capture_output=True, check=True"

check=True is really necessary.

try:
    subprocess.run(args, cwd, capture_output=True, check=True)
except subprocess.CalledProcessError as e:
    print("Error while executing YoloV5:")
    for k, v in e.__dict__.items():
        print(k)
        if isinstance(v, bytes):
            print(v.decode("utf-8"))
        else:
            print(v)
    raise Exception("Error in subcommand")

Upvotes: 0

Jason Stoller
Jason Stoller

Reputation: 55

Python 3.5 introduced the subprocess.run() method.

Here is the @kirbyfan64sos answer updated for Python >=3.5:

Run the process:

p = subprocess.run(['C:\\TGSSR\\test.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

In >=3.5, you can access the returncode, stdout, and stderr from the executed process.

To capture the error message:

stdout = p.stdout # stdout = normal output
stderr = p.stderr # stderr = error output

Check the process return code:

if p.returncode != 0:
# handle error

Upvotes: 3

kirbyfan64sos
kirbyfan64sos

Reputation: 10727

Run the process:

p = subprocess.Popen(['C:\\TGSSR\\test.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# shell = True is not needed

To capture the error message:

stdout, stderr = p.communicate()
# stdout = normal output
# stderr = error output

Check the process return code:

if p.returncode != 0:
    # handle error

Upvotes: 8

Wisperwind
Wisperwind

Reputation: 1011

If don't need all of Popen's functionality but just need to fetch stdout, you could also go for:

try:
    output = subprocess.check_output('C:\\TGSSR\\test.exe')
except subprocess.CalledProcessError as e:
    print("Oops... returncode: " + e.returncode + ", output:\n" + e.output)
else:
    print("Everything ok:\n" + output)

EDIT: As mgilson pointed out in the other answer, this requires a non-zero returncode on failures. If that isn't the case, you could try something along the lines of:

output = subprocess.check_output('C:\\TGSSR\\test.exe')
if "permission to access file denied" in output:
    print("Failed")

with some string that will only be on stdout in case of an error

Upvotes: 2

Related Questions