Python subprocess.check\u调用问题

Python subprocess.check\u调用问题,python,subprocess,Python,Subprocess,我知道我做错了什么 在shell中,我将键入: cuebreakpoints cuefile.cue | shnsplit -o flac flacfile.flac 这将根据提示文件拆分flac文件。由于我正在编写一个小型帮助工具(用Python)来转换flac文件,我显然想在代码中加入这一点 因此,我以一种蟒蛇式的方式写道: for root, dirs, files in os.walk(args): ... cmd = ('cuebreakpoints', cue, '

我知道我做错了什么

在shell中,我将键入:

cuebreakpoints cuefile.cue | shnsplit -o flac flacfile.flac
这将根据提示文件拆分flac文件。由于我正在编写一个小型帮助工具(用Python)来转换flac文件,我显然想在代码中加入这一点

因此,我以一种蟒蛇式的方式写道:

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


管道是否有问题?

如果要使用shell功能,如管道,则需要发出
check\u call
a
shell=True
kwarg并以单个字符串的形式发出命令:

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

但是请注意,
shell=True
与未初始化的
cue
flacs
一起使用时是一个字符串,如果您想使用shell功能,例如管道,则需要给
check_call
一个
shell=True
kwarg并以单个字符串的形式给出命令:

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

但请注意,
shell=True
与未初始化的
cue
flacs

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


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

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


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

这里有一点旁注

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

import shlex

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

subprocess.call(args ...)

这里有一点旁注

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

import shlex

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

subprocess.call(args ...)

谢谢,因为我不想使用shell=True,所以我同意jcollado的答案。当然你们都是对的,所以谢谢again@wagner-felix:如果您删除我在答案中输入的
,那么
管道。引用
应该足以清除文件名。不过,对于jcollado,+1。谢谢,因为我不想使用shell=True我同意jcollado的回答。当然你们都是对的,谢谢again@wagner-菲利克斯:如果你删除我在答案中输入的
,那么
管道。引用
应该足以对文件名进行清理。不过,对于jcollado来说+1。