具有复杂参数的Python子进程

yot*_*ota 1 python subprocess python-3.x

我正在寻找从python(3)调用shell命令的最安全和最方便的方法.这里是ps到pdf的转换:

 gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile="${pdf_file}" "${ps_file}"
Run Code Online (Sandbox Code Playgroud)

我使用subprocess,shlex并避免shell=True.但我发现结果命令不一致:

cmd = ['gs', '-dBATCH', '-dNOPAUSE', '-sDEVICE=pdfwrite', '-sOutputFile={0}'.format(pdf_filename), ps_filename]
Run Code Online (Sandbox Code Playgroud)

我错过了什么?!subprocess.call()语法看起来很干净,空格分隔的参数,在其他地方看起来一团糟.

在以下之间调用subprocess.call(cmd)(在python级别,即转义,注入保护,引用等)时有什么区别:

cmd = ['do', '--something', arg]
cmd = ['do', '--someting {0}'.format(arg)]
Run Code Online (Sandbox Code Playgroud)

如果没有,这也是一个很好的方法吗?

cmd = ['gs', '-dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile={0} {1}'.format(pdf_filename, ps_filename)]
Run Code Online (Sandbox Code Playgroud)

另一个不一致的例子:

hg merge -r 3 将会 cmd = ['hg', 'merge', '-r', revision_id]

hg merge --rev=3 将会 cmd = ['hg', 'merge', '--rev={0}'.format(revision_id)]

尽管如此,发送相同的参数有两种方法.

kam*_*mpu 6

区别在于命令可能有一个--something接受参数的选项,但它没有--something foo选项 - 这就是你要说的.当你在shell中运行命令时wc -l myfile.txt,你的shell会在命令行中找到空格 - 所以运行的命令是['wc', '-l', 'myfile.txt'].

subprocess模块不执行此类拆分.你必须自己做(除非你使用'shell'选项,但这通常不太安全,所以如果可以的话,请避免使用它.).

一些反例......

尝试运行名为"wc -l myfile.txt"的命令.当然,没有安装"wc -l myfile.txt"命令,只有"wc"命令,所以这会失败:

['wc -l myfile.txt']
Run Code Online (Sandbox Code Playgroud)

尝试使用选项"-l myfile.txt"运行命令"wc".有一个"-l"选项,但没有"-l myfile.txt"选项.这将失败:

['wc', '-l myfile.txt']
Run Code Online (Sandbox Code Playgroud)

和一个正确的例子:

['wc', '-l', 'myfile.txt']
Run Code Online (Sandbox Code Playgroud)

这会调用wc -l选项(仅打印行数)和myfile.txt唯一的文件名.

您可能会发现令人困惑的事情是这样的碎片:

'-sOutputFile={0}'

这是一种给出选项参数的"内联"风格.如果支持,程序的帮助通常会明确说明.Python没有拆分这些 - 接收它们的程序.

"内联"参数有三种主要风格.我将使用grep选项演示前两个:

--context=3
-C3
Run Code Online (Sandbox Code Playgroud)

(以上两行相同)

第三种类型只能在imagemagick和其他一些倾向于拥有大量命令行参数的程序中找到,例如gs:

-sOutputFile=foo
Run Code Online (Sandbox Code Playgroud)

这只是GNU标准的一个小变化 - 上面显示的long-option = VALUE表单.

GNU libc手册的"参数语法"部分提供了这些选项传递约定的完整说明.

  • 关于转义:没有进行转义,通常不需要转义.字符串值将完全按照您指定的顺序传递给命令.当然,没有引用也不需要引用,因为您已经在Python代码中处理了这个问题.

  • 关于注射:除非使用'shell'选项,否则这是不可能的.不要使用'shell'选项 :).