subprocess.Popen(“ echo $ HOME”…和subprocess.Popen([“ echo”,“ $ HOME”]之间有什么区别
问题内容:
我无法获得它与bash相关或python子进程,但结果不同:
>>> subprocess.Popen("echo $HOME", shell=True, stdout=subprocess.PIPE).communicate()
(b'/Users/mac\n', 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 "%s\n" "$@"' 'ick' 'foo' 'bar' 'baz'
将在单独的行上打印foo
,bar
和baz
。(这里使用“
zeroth”自变量-'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']
可以让您$HOME
在Python中访问的值。这也使您可以避免shell=True
,如果可以的话,通常应避免这种情况。