了解python subprocess.check_output的第一个参数和shell = True [重复]
Posted
技术标签:
【中文标题】了解python subprocess.check_output的第一个参数和shell = True [重复]【英文标题】:Understanding python subprocess.check_output's first argument and shell=True [duplicate] 【发布时间】:2014-01-28 12:44:53 【问题描述】:我对如何正确使用 Python 的 subprocess 模块感到困惑,特别是 check_output 方法的第一个参数和 shell
选项。查看下面交互式提示的输出。我将第一个参数作为列表传递,根据是否设置了shell=True
,我得到不同的输出。有人可以解释这是为什么以及输出的输出吗?
>>> import subprocess
>>> subprocess.check_output(["echo", "Hello World!"])
'Hello World!\n'
>>> subprocess.check_output(["echo", "Hello World!"], shell=True)
'\n'
现在,当我将第一个参数作为简单字符串而不是列表传递时,我得到了这个讨厌的堆栈跟踪。为什么会这样,这里发生了什么?
>>> subprocess.check_output("echo Hello World!")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 537, in check_output
process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1228, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
但是,当我打开 shell=True 时,它会完美运行:
>>> subprocess.check_output("echo Hello World!", shell=True)
'Hello World!\n'
所以我有点困惑,当第一个参数在没有shell=True
的列表中,然后作为带有shell=True
的简单字符串时,它可以工作。我不明白 shell=True
的作用以及将第一个 arg 作为列表与字符串传递之间的区别。
【问题讨论】:
【参考方案1】:来自Popen
的文档:
shell 参数(默认为
False
)指定是否使用 shell 作为要执行的程序。如果 shell 是True
,它是 建议将args
作为字符串而不是序列传递。在带有
shell=True
的Unix 上,shell 默认为/bin/sh
。 如果 args 是 字符串,字符串指定要通过shell执行的命令。 这意味着字符串必须完全按照它的格式进行格式化 在 shell 提示符下键入时。这包括,例如,引用或 反斜杠转义带有空格的文件名。 如果 args 是 序列,第一项指定命令字符串,任何 附加项将被视为 shell 的附加参数 本身。也就是说,Popen
相当于:Popen(['/bin/sh', '-c', args[0], args[1], ...])
在带有
shell=True
的 Windows 上,COMSPEC 环境变量指定 默认外壳。唯一需要指定shell=True
on Windows 是您希望执行的命令内置于 外壳(例如dir
或copy
)。您不需要shell=True
来运行批处理 文件或基于控制台的可执行文件。
在您的情况下,由于echo
是使用shell=True
启动时内置的shell,如果您想将参数传递给echo
命令,您必须将命令编写为一个字符串或传递一个具有 whole 命令的序列作为第一个元素的字符串。序列的其他元素作为参数传递到 shell,而不是你正在调用的命令。
在一些操作系统中,echo
也是一个程序(通常是/bin/echo
)。这解释了为什么您的第一个示例没有引发异常而是输出 '\n'
而不是预期的 'Hello, World!\n'
:/bin/echo
命令在没有参数的情况下执行,因为该参数已被 shell“消耗”。
调用时出现的错误:
subprocess.check_output("echo Hello World!")
是因为,因为你没有使用shell=True
,python 正在尝试执行程序echo Hello World!
,即名称为echo<space>Hello<space>World!
的程序。它是一个有效的程序名称,但你没有该名称的程序,因此例外。
【讨论】:
这似乎是一个 API 设计缺陷。shell
是 True/False
不足以证明第一个参数(命令)的含义发生如此剧烈(但无声)的变化。顺便说一句,新的asyncio
module 使用了两个不同的函数:subprocess_exec
和subprocess_shell
分别运行一个子进程和一个 shell 命令。
@J.F.Sebastian 他们可能应该添加一个shell_args
参数而不是重复使用args
。
是的,len(args) > 1 and shell=True
在大多数情况下是一个错误。【参考方案2】:
任何时候你使用shell=True
,你输入一个带引号的字符串作为check_output
的第一个参数,代表你通常输入到shell中的内容。 “在 shell=True 的 Unix 上,shell 默认为 /bin/sh
。”这为您提供了所有 shell 功能。 “这意味着字符串的格式必须与在 shell 提示符下键入时完全相同。” See Popen
【讨论】:
以上是关于了解python subprocess.check_output的第一个参数和shell = True [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Python subprocess.check_output()
当父进程死亡时,如何杀死使用 subprocess.check_output() 创建的 python 子进程?
python: subprocess.check_output 如何创建它的调用?
Python子进程subprocess.check_output和journalctl游标