I am using the following code to test for error capture when sending a command to the shell:
#!/usr/bin/python3
'''Trying to get a better error capture for subprocess.run'''
import subprocess
import argparse
cmd = 'ixconfig'
useShell = False
if useShell:
myCommand = cmd
else:
myCommand = cmd.split()
try:
result = subprocess.run(myCommand,
capture_output=True,
check=True,
shell=useShell,
text=True,
timeout=1,
)
except subprocess.TimeoutExpired:
print('Timeout occurred')
result = argparse.Namespace(err=f'"{myCommand}" timed out')
except subprocess.CalledProcessError as subErr:
print('subprocess.CalledProcessError')
result = argparse.Namespace(err=subErr)
except subprocess.SubprocessError as subErr:
print('except subprocess.SubprocessError')
result = argparse.Namespace(err=subErr)
# except:
# result = 'Poor way to handle an exception'
print(f'{result=}')
For the most part it works. I can get a CalledProcessError when I try to list an invalid directory (cmd = 'ls /var/log/xxx'
) or if I get a timeout (cmd = 'sleep 5'
).
However, if I send a bad command, such as cmd = 'ixconfig'
I get a traceback instead of capturing via SubprocessError:
Traceback (most recent call last):
File "/Users/shepherd/prog/aws/BBEditRunTemp-testSubprocess.py", line 17, in <module>
result = subprocess.run(myCommand,
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/subprocess.py", line 489, in run
with Popen(*popenargs, **kwargs) as process:
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/subprocess.py", line 854, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/subprocess.py", line 1702, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'ixconfig'
If I uncomment the straight except:
section, the exception is captured properly but I know a bare-except is poor programming. How can I properly capture a proper runtime exception?
The answer that works was supplied by @andrej-kesely:
except FileNotFoundError as subErr:
print('FileNotFoundError')
result = argparse.Namespace(err=subErr)