Reputation: 190
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
Reputation: 299
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
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
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
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