Документация Python нечеткая, но поведение не может скрыться от strace
.
Ваш Python код:
cmd = ['ls', '-la']
p1 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=True, text=True, capture_output=True)
p2 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=False, text=True, capture_output=True)
Превращается в (strace -f -e execve python3 foo.py
):
[pid 143557] execve("/bin/ls", ["ls", "-c", "-la"], 0x7fffc1235340 /* 34 vars */) = 0
[pid 143558] execve("/bin/ls", ["-la"], 0x7fffc1235340 /* 34 vars */) = 0
Что эквивалентно выполнению этих команд оболочки, что, как вы можете подтвердить, дает тот же результат, даже если обе они выполняются из оболочки.
ls -c -la # Generally equivalent to: ls -lca
( exec -a -la ls ) # Generally equivalent to: ls
Из этого мы может вывести поведение.
Если shell=True
, вызывается executable
. Список аргументов - это executable
, за которым следует стандартный флаг оболочки -c
, за которым следует args
. Это имеет больше смысла в случае executable='bash', args=['ls -la']
.
Если shell=False
, исполняемый файл вызывается. Список аргументов args
. Это имитирует execve
.
Так что по сути нет, здесь никакого обнаружения не происходит. Это просто два разных вызова ls
, и ни то, ни другое вы не хотели.