subprocess.Popen("echo $HOME"... 和 subprocess.Popen(["echo", "$HOME"]
Posted
技术标签:
【中文标题】subprocess.Popen("echo $HOME"... 和 subprocess.Popen(["echo", "$HOME"] 有啥区别?【英文标题】:What's the difference between subprocess.Popen("echo $HOME"... and subprocess.Popen(["echo", "$HOME"]subprocess.Popen("echo $HOME"... 和 subprocess.Popen(["echo", "$HOME"] 有什么区别? 【发布时间】:2020-04-25 17:55:18 【问题描述】:我无法理解它与 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)
为什么第二次只是换行符?争论在哪里消失?
【问题讨论】:
Actual meaning ofshell=True
in subprocess
的可能重复
【参考方案1】:
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
。 (“第零个”参数——这里是'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
的值。这也可以让你avoid shell=True
which you usually should if you can.
【讨论】:
有关(很多)更多详细信息,另请参阅***.com/questions/4256107/…【参考方案2】:在https://docs.python.org/2/library/subprocess.html#popen-constructor 上的文档中,如果您查看shell
参数,您会发现
shell 参数(默认为 False)指定是否使用 shell 作为程序来执行。如果 shell 为 True,建议将 args 作为字符串而不是序列传递。
这意味着当您执行第二个命令时,它会以echo
运行,因此您只会得到一个新行。
【讨论】:
【参考方案3】:当您拥有shell=True
时,实际运行的进程是shell 进程,即认为它在unix 上运行/bin/sh -c
。您传递给 Popen 的参数作为参数传递给这个 shell 进程。所以/bin/sh -c 'echo' '$HOME'
打印换行符,第二个参数被忽略。所以通常你应该只使用带有shell=True
的字符串参数。
【讨论】:
以上是关于subprocess.Popen("echo $HOME"... 和 subprocess.Popen(["echo", "$HOME"] 的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Subprocess.popen() 与 pyinstaller 一起使用?
如何在 Python 2 中将字符串传递给 subprocess.Popen? [复制]
将python中的双引号shell命令传递给subprocess.Popen()?
Windows 上的 Python 2.6:如何使用“shell=True”参数终止 subprocess.Popen?