Search code examples
pythonpython-3.xexception

Exception Handling for subprocess.run


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?


Solution

  • The answer that works was supplied by @andrej-kesely:

    except FileNotFoundError as subErr:
        print('FileNotFoundError')
        result = argparse.Namespace(err=subErr)