了解 python subprocess.check_output 的第一个参数和 shell=True [英] Understanding python subprocess.check_output's first argument and shell=True

查看:37
本文介绍了了解 python subprocess.check_output 的第一个参数和 shell=True的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对如何正确使用 Python 的 subprocess 模块感到困惑,特别是 check_output 方法的第一个参数和 shell 选项.查看下面交互式提示的输出.我将第一个参数作为列表传递,根据是否设置了 shell=True,我得到不同的输出.有人可以解释为什么会这样以及输出的输出吗?

<预><代码>>>>导入子流程>>>subprocess.check_output(["echo", "Hello World!"])'世界你好! '>>>subprocess.check_output(["echo", "Hello World!"], shell=True)' '

现在,当我将第一个参数作为简单字符串而不是列表传递时,我得到了这个讨厌的堆栈跟踪.为什么会这样?这里发生了什么?

<预><代码>>>>subprocess.check_output("echo Hello World!")回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中文件/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py",第 537 行,在 check_output 中进程 = Popen(stdout=PIPE, *popenargs, **kwargs)文件/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py",第 679 行,在 __init__ 中错误读取,错误写入)文件/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py",第 1228 行,在 _execute_child引发 child_exceptionOSError: [Errno 2] 没有那个文件或目录

但是,当我打开 shell=True 时,它​​可以完美运行:

<预><代码>>>>subprocess.check_output("echo Hello World!", shell=True)'世界你好! '

所以我有点困惑,当第一个 arg 在没有 shell=True 的列表中时它起作用,然后作为一个简单的字符串 WITH shell=True.我不明白 shell=True 的作用以及将第一个 arg 作为列表与字符串传递之间的区别.

解决方案

来自 Popen:

<块引用>

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

在带有 shell=True 的 Unix 上,shell 默认为 /bin/sh.如果 args 是一个string,字符串指定通过shell执行的命令.这意味着字符串必须完全按照原样格式化在 shell 提示符下键入时.这包括,例如,引用或反斜杠转义带有空格的文件名.如果 args 是一个序列,第一项指定命令字符串,任何附加项目将被视为 shell 的附加参数本身.也就是说,Popen 相当于:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

在带有 shell=True 的 Windows 上,COMSPEC 环境变量指定默认外壳.您唯一需要在上指定 shell=TrueWindows 是您希望执行的命令内置于shell(例如 dircopy).您不需要 shell=True 来运行批处理文件或基于控制台的可执行文件.

在您的情况下,由于 echo 是使用 shell=True 启动时内置的 shell,如果您想将参数传递给 echo 命令你必须要么把命令写成一个字符串,要么传递一个将整个命令作为一个字符串作为第一个元素的序列.序列的其他元素作为参数传递给外壳,而不是传递给您正在调用的命令.

某些操作系统中,echo也是一个程序(通常是/bin/echo).这解释了为什么您的第一个示例没有引发异常而是输出 ' ' 而不是预期的 'Hello, World! ':/bin/echo 命令在没有参数的情况下执行,因为该参数已被 shell 消耗".

调用时出现的错误:

subprocess.check_output("echo Hello World!")

是因为你没有使用shell=True,python正在尝试执行程序echo Hello World! 即一个名为 echoHelloWorld! 的程序.它是一个有效的程序名称,但您没有使用该名称的程序,因此是个例外.

I'm confused on how to correctly use Python's subprocess module, specifically, the check_output method's first argument and the shell option. Check out the output from the interactive prompt below. I pass the first argument as a list and depending on whether shell=True is set, I get different output. Can someone explain why this is and the output that is outputted?

>>> import subprocess
>>> subprocess.check_output(["echo", "Hello World!"])
'Hello World!
'
>>> subprocess.check_output(["echo", "Hello World!"], shell=True)
'
'

Now when I pass the first argument as a simple string instead of a list, I get this nasty stack trace. Why is that and what's going on here?

>>> 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

However, when I turn on shell=True, it then works perfectly:

>>> subprocess.check_output("echo Hello World!", shell=True)
'Hello World!
'

So I'm a little confused, it works when the first arg is in a list WITHOUT shell=True and then works as a simple string WITH shell=True. I'm not understanding what shell=True does and the difference between passing the first arg as a list vs a string.

解决方案

From the documentation of Popen:

The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. If shell is True, it is recommended to pass args as a string rather than as a sequence.

On Unix with shell=True, the shell defaults to /bin/sh. If args is a string, the string specifies the command to execute through the shell. This means that the string must be formatted exactly as it would be when typed at the shell prompt. This includes, for example, quoting or backslash escaping filenames with spaces in them. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. That is to say, Popen does the equivalent of:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

On Windows with shell=True, the COMSPEC environment variable specifies the default shell. The only time you need to specify shell=True on Windows is when the command you wish to execute is built into the shell (e.g. dir or copy). You do not need shell=True to run a batch file or console-based executable.

In your case, since echo is a shell built-in when launched with shell=True, if you want to pass arguments to the echo command you must either write the command as a string or pass a sequence that has the whole command as a string as first element. Other elements of the sequence are passed as arguments to the shell, not to the command you are invoking.

In some OSes echo is also a program (usually /bin/echo). This explains why your first example didn't raise an exception but outputs ' ' instead of the expected 'Hello, World! ': the /bin/echo command was executed without arguments, because the argument was "consumed" by the shell.

The error raised when calling:

subprocess.check_output("echo Hello World!")

is due to the fact that, since you did not use shell=True, python is trying to execute the program echo Hello World! i.e. a program that has the name echo<space>Hello<space>World!. It is a valid program name, but you there's no program with that name, hence the exception.

这篇关于了解 python subprocess.check_output 的第一个参数和 shell=True的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆