Python subprocess.check_call问题

时间:2011-12-13 13:02:46

标签: python subprocess

我知道我做错了什么。

在shell中我会输入:

cuebreakpoints cuefile.cue | shnsplit -o flac flacfile.flac

然后根据cuefile分割flac文件。由于我正在编写一个小的帮助工具(在Python中)来转换flac文件,我显然希望将这一点合并到我的代码中。

所以我用pythonic的方式写道:

for root, dirs, files in os.walk(args):
    ...
    cmd = ('cuebreakpoints', cue, '|', 'shnsplit', '-o', 'flac', flacs[0])
    subprocess.check_call(cmd, cwd=None)
    ....

'cue'是cuefile,'flacs [0]'是flac文件。但是我得到了:

  

subprocess.CalledProcessError:命令'('cuebreakpoints','41_30sec.cue','|','shnsplit',' - o','flac','41_30sec.flac')'返回非零退出状态1

因为PIPE有问题吗?

3 个答案:

答案 0 :(得分:2)

如果你想使用管道等shell功能,你需要给check_call一个shell=True kwarg并将命令作为单个字符串提供:

check_call("cuebreakpoints '%s' | shnsplit -o flac '%s'" % (cue, flacs[0]),
           shell=True)

但请注意,shell=True与未经审核的cueflacs一起使用时为potential security hazard

答案 1 :(得分:2)

作为将命令字符串传递给shell(并跳过larsmans指出的安全问题)的替代方法,您可以创建两个subprocess.Popen对象并将第一个的输出连接到第二个的输入一个(这基本上就是shell会为你做的):

有关如何执行此操作的示例,请查看文档中的replacing shell pipeline部分。

答案 2 :(得分:0)

这里有一点注意事项。

使用子命令编写python脚本时,我发现shlex对于解析更复杂的命令非常有帮助,而不必过多担心列表的外观。

import shlex

...
cmd = "cuebreakpoints '%s' | shnsplit -o flac '%s'" % (cue, flacs[0])
args = shlex.split(cmd)

subprocess.call(args ...)