具有复杂参数的Python子进程

2024-10-01 00:23:09 发布

您现在位置:Python中文网/ 问答频道 /正文

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

 gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile="${pdf_file}" "${ps_file}"

我使用subprocessshlex并避免{}。 但我发现生成的命令不一致:

^{pr2}$

我错过了什么?!subprocess.call()使用空格分隔的参数时,语法看起来非常干净,而其他地方的语法则显得一团糟。在

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

cmd = ['do', '--something', arg]
cmd = ['do', '--someting {0}'.format(arg)]

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

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

另一个不一致的例子:

hg merge -r 3将是{}

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

尽管事实如此,这是两种发送相同论点的方法。在


Tags: 方法命令cmdgsformatpdfmergehg
2条回答

区别在于命令可能有一个接受参数的 something选项,但它没有 something foo选项,这正是您要告诉它的。当您在shell中运行命令时,比如wc -l myfile.txt,shell会将它找到空格的命令行拆分成['wc', '-l', 'myfile.txt']。在

subprocess模块不执行这种拆分。你必须自己去做(除非你使用“shell”选项,但这通常不太安全,所以尽可能避免它)。在

一些反例子。。。在

尝试运行一个名为“wc-l”的命令我的文件.txt". 当然,没有“wc-l”我的文件.txt“命令已安装,只有一个“wc”命令,因此这将失败:

['wc -l myfile.txt']

尝试运行带有“-l”选项的命令“wc”我的文件.txt". 有“-l”选项,但没有“-l”我的文件.txt“选项。这将失败:

^{2}$

一个正确的例子:

['wc', '-l', 'myfile.txt']

这将使用-l选项(仅打印行计数)和myfile.txt作为唯一的文件名调用wc。在

你可能会发现一些令人困惑的片段,比如:

'-sOutputFile={0}'

这是一种提供选项参数的“内联”样式。如果支持这一点,程序的帮助通常会明确说明。Python不会像接收它们的程序那样分割它们。在

“inline”参数有三种主要样式。我将使用grep选项演示前两个:

 context=3
-C3

(以上两行相当)

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

-sOutputFile=foo

这只是上面显示的GNU标准long option=VALUE形式的一个小变化。在

The GNU libc manual's "argument syntax" section给出了这些选项传递约定的完整解释。在

  • 关于逃逸:没有逃逸,通常也不需要逃逸。字符串值将完全按照指定的传递给命令。当然,不需要引用,因为您已经在Python代码中处理过了。

  • 关于注入:除非使用“shell”选项,否则这是不可能的。不要使用“shell”选项:)。

你问的有什么不同。。易于检查:

arg = 'foo'

cmd = ['do', ' something', arg]
print cmd
cmd = ['do', ' someting {0}'.format(arg)]
print cmd

>>> 
['do', ' something', 'foo']
['do', ' someting foo']

正如你所看到的,它们是不一样的。在

为了正确调用子流程,应执行以下操作:

^{2}$

或者:

cmd = 'gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile={0} {1}'.format(pdf_filename, ps_filename)
subprocess.Popen(cmd, shell=True, ...)

使用参数列表或字符串之间的区别:

当您使用参数列表时,您将这些参数作为参数传递给shell(或者如果指定了可执行文件)

当你用shell=True发送一个字符串时,你可以让shell解析字符串并生成自己的参数。。。在

所以['do', ' something', 'foo']是3个参数,而['do', ' someting foo']只有2个参数。在

相关问题 更多 >