在子进程方法中列表优先于字符串

时间:2014-03-24 15:44:25

标签: python subprocess

在子进程方法中使用list over string有什么好处?到目前为止我理解的那些:

  • 输入来自外部来源时的安全性
  • 不同操作系统的可移植性

还有其他人吗?

在我的特定情况下,我使用子进程库来运行软件测试。输入不是来自外部来源。测试仅在Linux上运行。因此,我认为列表对字符串没有任何好处。

1 个答案:

答案 0 :(得分:2)

在POSIX上,列表和字符串参数具有不同的含义,并在不同的上下文中使用。

使用字符串参数和shell=True来运行shell命令,例如:

from subprocess import check_output

output = check_output("dmesg | grep hda", shell=True)

list参数用于运行没有shell的命令,例如:

from subprocess import check_call

check_call(["ls", "-l"])

一个例外是call("ls")等同于call(["ls"])(没有参数的命令)。

您应该使用带有shell=False的列表参数(默认值),除非在需要 shell的情况下,因此使用字符串参数。

使用list参数和shell=True几乎总是错误的(在这种情况下,参数被解释为shell本身的参数而不是命令)。不要使用它。

如果您的问题:shell=False的优点是什么,因此列表参数优于字符串参数:

  • 你不需要转义参数,没有shell插值,如分词,参数扩展,命令替换等:你看到的是你得到的
    • 支持带空格的参数
    • 支持带引号,美元符号等特殊字符的参数
  • 很明显,参数边界在哪里。它们明显分开。
  • 很清楚执行什么程序:它是列表中的第一项
  • 从不受信任的来源填充的参数无法执行任意命令
  • 为什么要运行多余的shell进程,除非你需要它

有时,在源代码中将参数指定为字符串可能更方便/可读; shlex.split()可用于将其转换为列表:

import shlex
from subprocess import check_call

cmd = shlex.split('/bin/vikings -input eggs.txt -output "spam spam.txt" '
                  '''-cmd "echo '$MONEY'"''')
check_call(cmd)

请参阅the docs


在Windows上,参数的解释方式不同。本机格式是一个字符串,传递的列表使用subprocess.list2cmdline()函数转换为字符串,该函数可能不适用于所有Windows程序。 shell=True仅用于运行内置shell命令。

如果list2cmdline()为您的可执行文件创建了正确的命令行(不同的程序可能使用不同的规则来解释命令行),那么可以使用list参数来实现可移植性并避免手动转义单独的参数。