python subprocess.call终止,恕不另行通知

时间:2013-12-30 16:32:14

标签: python

我在python中有一个脚本调用子进程来编码

下面的视频文件
        args1 = ["ffmpeg", "-i", "my niece.mkv"]
        args2 = MyConfig.DefaultFFMPEGParam + " " + crf + " " + output + ""
        args = args2.split(' ')
        args1.extend(args)

        print "EncodeReal : " + uniqueno + " : Try Encode"
        print " ".join(args1)
        subprocess.call(" ".join(args1), shell=True)

print语句成功打印出以下命令

ffmpeg -i "/home/Downloads/my niece.mkv" -tune animation -keyint_min 12 -sc_threshold 45 -bf 8 -b_strategy 2 -refs 10 -qmin 10 -qmax 51 -qcomp 0.6 -direct-pred auto -me_range 24 -me_method umh -subq 9 -trellis 2 -vcodec libx264 -crf 28.0 /home/Downloads/output.mkv

如果在脚本中运行此命令它运行良好,但如果它由subprocess.call运行,则会遇到

ffmpeg version git-2013-12-30-61d43a2 Copyright (c) 2000-2013 the FFmpeg developers
  built on Dec 30 2013 11:02:28 with gcc 4.4.7 (GCC) 20120313 (Red Hat 4.4.7-4)
  configuration: --prefix=/root/ffmpeg_build --extra-cflags=-I/root/ffmpeg_build/include --extra-ldflags=-L/root/ffmpeg_build/lib --bindir=/root/bin --extra-libs=-ldl --enable-gpl --enable-nonfree --enable-libfdk_aac --enable-libx264
  libavutil      52. 59.100 / 52. 59.100
  libavcodec     55. 47.100 / 55. 47.100
  libavformat    55. 22.101 / 55. 22.101
  libavdevice    55.  5.102 / 55.  5.102
  libavfilter     4.  0.103 /  4.  0.103
  libswscale      2.  5.101 /  2.  5.101
  libswresample   0. 17.104 /  0. 17.104
  libpostproc    52.  3.100 / 52.  3.100


[1]+  Stopped                 python MonitorService.py

它自行停止!有什么原因吗?

2 个答案:

答案 0 :(得分:1)

您的代码示例无法生成您提供的打印字符串。

假设您的代码与您在示例中显示的一样,那么Bakuriu已经指出输入文件名周围的引号将丢失,并且ffmpeg将无法正确处理文件名中的嵌入空间。我还注意到输入文件的路径没有显示在你的代码中,这将是你的python应用程序没有用完该目录的问题。

尝试按如下方式修改代码:

args1 = ["ffmpeg", "-i", '"my niece.mkv"']

请注意添加单引号以确保文件名包含在双引号中。

答案 1 :(得分:1)

我完全同意@RogueThinking。您的问题是"my niece.mkv"中的空格。解决此问题的另一种方法是将subprocess.call与可迭代的参数列表一起使用,而不是连接完整的字符串。这些参数将被正确传递,而不必担心引用转义。

documentation for subprocess(强调添加):

  

所有调用都需要args,并且应该是字符串或序列   程序参数。 通常提供一系列参数   首选,因为它允许模块处理任何所需的   转义和引用参数(例如,允许文件中的空格   名称)即可。如果传递单个字符串,则任何一个shell都必须为True(请参阅   或者字符串必须简单地命名要执行的程序   没有指定任何参数。

例如,使用列表的完整工作版本如下所示:

import subprocess

def run():
    DefaultFFMPEGParam = "-tune animation -keyint_min 12 -sc_threshold 45 -bf 8 -b_strategy 2 -refs 10 -qmin 10 -qmax 51 -qcomp 0.6 -direct-pred auto -me_range 24 -me_method umh -subq 9 -trellis 2 -vcodec libx264" \
        .split(' ')
    crf = ['-crf', '28.0']
    output = "output2.mkv"

    # list concatenation
    args1 = ["ffmpeg", "-i", "my niece.mkv"] + DefaultFFMPEGParam + crf + [output,]

    print args1
    # prints:
    #
    # ['ffmpeg', '-i', 'my niece.mkv', '-tune', 'animation', '-keyint_min', '12',
    #  '-sc_threshold', '45', '-bf', '8', '-b_strategy', '2', '-refs', '10', '-qmin',
    #  '10', '-qmax', '51', '-qcomp', '0.6', '-direct-pred', 'auto', '-me_range', '24',
    #  '-me_method', 'umh', '-subq', '9', '-trellis', '2', '-vcodec', 'libx264',
    #  '-crf', '28.0',
    #  'output2.mkv']    

    subprocess.call(args1)

run()

请注意,在这种情况下,我可以省略shell=True,并且呼叫仍然可以正常执行。