子流程之间有什么区别。波彭( "echo $HOME" ...和子流程。波彭([ "echo" , "$HOME" ]



我无法理解它与bash相关或python子进程,但结果不同:

>>> subprocess.Popen("echo $HOME", shell=True, stdout=subprocess.PIPE).communicate()
(b'/Users/macn', None)
>>> subprocess.Popen(["echo", "$HOME"], shell=True, stdout=subprocess.PIPE).communicate()
(b'n', None)

为什么第二次只是换行符?争论在哪里下降?

subprocess.Popen()的第一个参数告诉系统要运行什么。

当它是列表时,您需要使用shell=False.巧合的是,它恰好在 Windows 中如您所愿地工作;但是在类Unix平台上,你只是传入了一些通常会被忽略的参数。有效

/bin/sh -c 'echo' '$HOME'

这只会导致第二个参数不用于任何内容(我使用单引号来强调这些只是静态字符串(。

以我的拙见,在这种情况下,Python 应该抛出一个错误。在Windows上也是如此。这是一个应该捕获并报告的错误。

(在相反的情况下,指定了shell=False但您传入的字符串不是有效命令的名称,无论如何您最终都会收到错误,如果您甚至对正在发生的事情有一个模糊的概念,这是有意义的。

如果你真的知道你在做什么,你可以让第一个参数访问后续参数;例如

/bin/sh -c 'printf "%sn" "$@"' 'ick' 'foo' 'bar' 'baz'

将在单独的行上打印foobarbaz。("零"参数 - 此处为'ick'- 用于填充$0。但这只是一个晦涩的推论;不要试图将其用于任何事情。

另外,如果您只想运行命令,则不应使用subprocess.Popen()subprocess.run()文档更详细地介绍了这一点。 使用text=True,您将获得一个字符串而不是字节。

result = subprocess.run('echo "$HOME"', shell=True,
text=True, capture_output=True, check=True)
print(result.stdout, result.stderr)

当然,os.environ['HOME']允许您从 Python 中访问$HOME的价值。这也使您可以避免通常应该避免shell=True如果可以的话。

在 https://docs.python.org/2/library/subprocess.html#popen-constructor 上找到的文档中,如果您查看shell参数,您会发现

shell

参数(默认为 False(指定是否使用 shell 作为要执行的程序。如果 shell 为 True,建议将 args 作为字符串而不是序列传递。

这意味着当您执行第二个命令时,它会以echo运行,因此您只会得到一个新行。

当你有shell=True时,实际运行的进程是shell进程,即,认为它在unix上运行/bin/sh -c。您传递给 Popen 的参数将作为参数传递给此 shell 进程。因此,/bin/sh -c 'echo' '$HOME'打印换行符,第二个参数被忽略。所以通常你应该只对shell=True使用字符串参数。

最新更新