utils: inc. captured stdout / stderr when forging CalledProcessError

When executing a command via arun_command with check=True, we forge
and then raise a CalledProcessError exception if the command exits
abnormally (i.e., exit code != 0).

When doing so, we only instantiate the exception with the exit code and
the command executed. This means that we lose access to any output
captured so far. This is usually fine for stdout but stderr oftentimes
contains invaluable information to understand what caused the command to
exit abnormally.

Back in Python 3.5, stdout and stderr were introduced as new attributes
for CalledProcessError.
We now also include stdout and stderr in the CalledProcessError
instances that we forge. This allows us to access stderr (if any) when
catching the exception with:

  try:
      ...
  except CalledProcessError as exc:
      print(exc.stderr)

Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
Olivier Gayot 2022-11-21 14:49:00 +01:00
parent fa0aa32117
commit fcebcac568
1 changed files with 2 additions and 1 deletions

View File

@ -102,7 +102,8 @@ async def arun_command(cmd: Sequence[str], *,
# .communicate() forces returncode to be set to a value # .communicate() forces returncode to be set to a value
assert(proc.returncode is not None) assert(proc.returncode is not None)
if check and proc.returncode != 0: if check and proc.returncode != 0:
raise subprocess.CalledProcessError(proc.returncode, cmd) raise subprocess.CalledProcessError(proc.returncode, cmd,
stdout, stderr)
else: else:
return subprocess.CompletedProcess( return subprocess.CompletedProcess(
cmd, proc.returncode, stdout, stderr) cmd, proc.returncode, stdout, stderr)