I am trying to create a function that can run any shell command and return the stdout of that command, without worrying about any exceptions that could be thrown. When testing the code written below with incorrect commands like xyz testing
, I get a FileNotFoundError
rather that the CalledProcessError
even though the command xyz testing
returns a non-zero return code when I ran it in the shell. But, when I run the same function with a similar invalid command like ls -xyz
I get a CalledProcessError
as expected. Does anyone know why the exception is not being thrown in a consistent manner.
try:
cmd_result = subprocess.run(
cmd,
capture_output=True,
text=True,
check=True,
)
except subprocess.CalledProcessError as exc:
click.echo(exc.stderr)
click.echo(cmd)
sys.exit(1)
Thank you
I tried putting the shell=True
option, and then the error situation swaps (xyz testing
) passes and ls -xyz
fails.
I have been stuck on what else I can try.
CodePudding user response:
A couple of things are happening. With check=True
, subprocess raises CalledProcessError
if the command is executed and returns a non-zero exit status. When shell=False
, the file to execute couldn't be found, so you got the FileNotFound
error code. The program wasn't run, there was no exit code to examine, so CalledProcessError
was not an option.
When shell=True
, subprocess runs an intermediate shell. Now its the shell return code that matters and that can be different than the called process. Subprocess found the intermediate shell, so there is no FileNotFound
error, but couldn't find the program so returned a non-zero value, generating the other exception. Consider the command "xyz testing;exit 0"
this would not generate a called process error even though xyz does not exist. That's because the shell returned a 0 exit code.