subprocess中命令为参数序列和字符串的区别

参数args

参数args可以是一个参数序列,也可以是一个单独的字符串。参数序列通常是首选的,因为它允许模块处理参数的转义和引号(例如,允许文件名中有空格)。

如果传递参数序列,默认情况下,程序执行序列的第一个元素,后面所有的元素都作为参数。

如果传一个单独字符串,要么参数shell为True,要么字符串必须没有指定任何参数的可执行程序的名称。

所以,一般的搭配是参数序列和shell=False,字符串和shell=True

参数shell

shell参数设置是否在单独的shell中执行命令。如果shell=True,则是派生一个新的shell来解释执行命令。如果你使用Python主要是为了增强它在大多数系统shell上提供的控制流,并且还想方便的访问shell特性,如shell的管道符、文件通配符、环境变量扩展或者~扩展到home目录等,这个参数将非常有用。

不同平台下shell参数使用

shell=False
对于Unix平台,如果args是字符串,这个字符串将被解释为程序的名称或路径,然后被执行。然而,这仅仅只有在不给这个程序传递任何参数时才能被执行。

import subprocess
subprocess.Popen('ls', shell=False)  # get the result
subprocess.Popen('ls', shell=False)  # raise Exception: FileNotFoundError

对于windows平台,如果args是个序列,它将被转换成一个字符串通过以下方式:Converting an argument swquence to a string on Windows ,这是因为底层的CreateProcess()只能操作字符串。

shell=True

在Unix平台下shell=True,shell默认为/bin/sh。如果args是字符串,通过shell执行字符串指定的命令。这意味着字符串的格式必须与在shell提示符下键入时的格式完全相同。例如, 使用引号或反斜杠转义包含空格的文件名。如果args是一个序列,第一个元素指定了命令字符串,其它的元素他的参数。

在Windows平台下shell=True,环境变量COMSPEC指定了默认的shell。只有当你想要执行的命令内置于shell中时,你才需要指定shell=True(例如dircopy)。运行批处理文件或基于控制台的可执行文件不需要shell=True

args的参数序列和字符串的区别

这里的字符串指的是shell=True下的字符串

  • 使用序列不需要派生一个新的shell解释器。所以比字符串更快一点
  • 使用shell参数容易引起shell注入漏洞,使用shlex.quote() 函数可以正确转义空格和shell命令中的元字符

参考

Tags: