I am trying to understand the return code of subprocess.run
:
>>> subprocess.run('false | true', shell=True)
CompletedProcess(args='false | true', returncode=0)
>>> subprocess.run(['false', '|', 'true'])
CompletedProcess(args=['false', '|', 'true'], returncode=1)
>>> subprocess.run(['false', '|', 'true'], shell=True)
CompletedProcess(args=['false', '|', 'true'], returncode=1)
It looks like specifying cmd
as a list of strings also sets the pipefail
shell option:
$ false | true
$ echo $?
0
$ set -o pipefail
$ false | true
$ echo $?
1
I can't find any information about this in the documentation of the subprocess module. I am using python 3.6. Does anyone know how this works?
This doesn't do what you think:
>>> subprocess.run(['false', '|', 'true'], shell=True)
When you pass a list of strings to subprocess.run
and specify shell=True
, only the first item is interpreted as a command (the remaining items are provided as arguments to the shell). Compare the output of:
>>> subprocess.run('echo hello world', shell=True)
hello world
CompletedProcess(args='echo hello world', returncode=0)
With:
>>> subprocess.run(['echo', 'hello', 'world'], shell=True)
CompletedProcess(args=['echo', 'hello', 'world'], returncode=0)
With:
>>> subprocess.run(['echo $0 $1', 'hello', 'world'], shell=True)
hello world
CompletedProcess(args=['echo $0 $1', 'hello', 'world'], returncode=0)
So what you have there is equivalent to:
>>> subprocess.run('false', shell=True)
And do you know why the return codes of subprocess.run('false | true', shell=True) and subprocess.run(['false', '|', 'true']) are different?
Because the first runs false | true
false | true
, which is a pipeline. The exit code of a pipeline is the exit code of the last command in the pipeline (in this case true
). The second call, as discussed here, just runs false
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.