Handling Subprocess Errors/shaare/wBVnmg
Handling Subprocess Errors
- External commands can fail in multiple ways: non-zero exit codes, missing executables, or hanging processes.
- Using
subprocess.run(..., check=True)shifts return-code checks into exceptions you can catch. - Specific exception types (
CalledProcessError,FileNotFoundError,TimeoutExpired) let you distinguish failure modes and respond appropriately.
subprocess.CalledProcessError Attributes
e.returncode: the non-zero exit status of the command.e.cmd: the exact command invoked (list or string form).e.stdout/e.output: captured standard output, ifcapture_output=True.e.stderr: captured standard error, ifcapture_output=True.- These attributes let you log or display detailed diagnostics when a command fails.
import subprocess
cmd = ["ls", "missing_dir"]
try:
subprocess.run(cmd, check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as err:
print(f"Command executed: {err.cmd}")
print(f"Return code {err.returncode}")
print(f"STDOUT capture: {err.stdout}")
print(f"STDERR capture: {err.stderr}")
Handling FileNotFoundError
- If the executable itself isn’t in
PATH,subprocess.run()raisesFileNotFoundErrorbefore running. - Catching it separately lets you inform the user that a required tool isn’t installed, rather than treating it as a generic failure.
import subprocess
cmd = ["fakecmd", "--version"]
try:
subprocess.run(cmd, check=True, capture_output=True, text=True)
except FileNotFoundError as err:
print("FileNotFoundError caught!")
print(f" The command '{cmd[0]}' was not found on this system.")
Handling subprocess.TimeoutExpired
- Adding
timeout=<seconds>tosubprocess.run()kills the process if it runs too long. - A
TimeoutExpiredexception is raised, containingcmd,timeout, and any partialstdout/stderr. - Use this to prevent hung scripts and to implement retry or fallback logic.
import subprocess
cmd = ["sleep", "5"]
try:
subprocess.run(cmd, timeout=2, capture_output=True, text=True)
print("Command completed within timeout.")
except subprocess.TimeoutExpired as err:
print("TimeoutExpired caught!")
print(f" Command: {err.cmd}")
print(f" Timeout after {err.timeout} seconds")
Recommended Error Handling Strategy
- Wrap
subprocess.run()in atryblock. - First catch
FileNotFoundErrorto detect missing executables. - Next catch
subprocess.TimeoutExpiredif you use timeouts. - Then catch
subprocess.CalledProcessErrorfor non-zero exits. - Finally, if necessary, an
except Exceptionblock can log any other unexpected issues. - This layered approach keeps your script robust and your errors informative.
+++
(97)