Python subprocess.check_call 问题
我知道我做错了什么。
在命令行里,我会输入:
cuebreakpoints cuefile.cue | shnsplit -o flac flacfile.flac
这样就可以根据cue文件来分割flac文件。因为我正在写一个小工具(用Python)来转换flac文件,所以我想把这部分代码放进我的程序里。
所以我用Python的方式写了:
for root, dirs, files in os.walk(args):
...
cmd = ('cuebreakpoints', cue, '|', 'shnsplit', '-o', 'flac', flacs[0])
subprocess.check_call(cmd, cwd=None)
....
这里的'cue'是指cue文件,而'flacs[0]'是指flac文件。但是我遇到了一个错误:
subprocess.CalledProcessError: 命令 '('cuebreakpoints', '41_30sec.cue', '|', 'shnsplit', '-o', 'flac', '41_30sec.flac')' 返回了非零的退出状态 1
是不是因为PIPE的原因导致的问题?
3 个回答
0
这里有个小提示。
在用 Python 写脚本的时候,如果需要使用子命令,我发现 shlex 这个工具特别有用。它可以帮助我们处理更复杂的命令,而不用太担心最终的命令列表会是什么样子。
import shlex
...
cmd = "cuebreakpoints '%s' | shnsplit -o flac '%s'" % (cue, flacs[0])
args = shlex.split(cmd)
subprocess.call(args ...)
2
如果你想使用一些像管道这样的命令行功能,你需要在调用 check_call
时加上 shell=True
这个参数,并且把命令写成一个完整的字符串:
check_call("cuebreakpoints '%s' | shnsplit -o flac '%s'" % (cue, flacs[0]),
shell=True)
但是要注意,当你用未处理过的 cue
或 flacs
时,使用 shell=True
可能会带来 安全隐患。
2
为了避免将命令字符串传递给一个外壳程序(这样可以避免larsmans提到的安全问题),你可以创建两个 subprocess.Popen
对象,并将第一个对象的输出连接到第二个对象的输入(这基本上就是外壳程序为你做的事情):
关于如何做到这一点的例子,请查看文档中的 替代外壳管道 部分。