2014-05-13 118 views
1

我有一個python腳本通過子進程調用ffmpeg來做一些mp3操作。它在前臺運行良好,但是如果我在後臺運行它,它可以達到ffmpeg命令,它本身可以將其配置轉儲到stderr中。此時,一切都停止,並且父任務被報告爲停止,而不會在任何地方引發異常。我已經在ffmpeg的地方嘗試了一些其他簡單的命令,它們通常在前景或背景中執行。在後臺調用ffmpeg殺死腳本

這是問題的小例子:

import subprocess 

inf = "3HTOSD.mp3" 
outf = "out.mp3" 

args = [ "ffmpeg", 
      "-y", 
      "-i", inf, 
      "-ss", "0", 
      "-t", "20", 
      outf 
     ] 

print "About to do" 

result = subprocess.call(args) 

print "Done" 

我真的不能工作了,爲什麼還是包裝過程中如何使家長沒有至少提高一個錯誤終止,只有如何發生在一個很小的環境中。到底是怎麼回事?另外,我知道ffmpeg不是最好的包,但我與使用ffmpeg編譯到它的東西接口,所以再次使用它似乎是明智的。

回答

1

這可能與Linux process in background - 「Stopped」 in jobs?例如,使用parent.py

from subprocess import check_call 

check_call(["python", "-c", "import sys; sys.stdin.readline()"]) 

要重現該問題: 「parent.py腳本顯示爲停止」 如果你在bash中運行它作爲後臺作業:

$ python parent.py & 
[1] 28052 
$ jobs 
[1]+ Stopped     python parent.py 

如果父母process is in an orphaned process group then it is killed on receiving SIGTTIN signal (a signal to stop)

解決辦法是重新輸入:

import os 
from subprocess import check_call 
try: 
    from subprocess import DEVNULL 
except ImportError: # Python 2 
    DEVNULL = open(os.devnull, 'r+b', 0) 

check_call(["python", "-c", "import sys; sys.stdin.readline()"], stdin=DEVNULL) 

如果你不需要看ffmpeg的標準輸出/標準錯誤;你也可以重定向到/dev/null

check_call(ffmpeg_cmd, stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT) 
+0

這個。感謝你的解釋,整個「等待stdin」的東西是我未知的未知之一。實現最簡單的解決方案就是將一個subprocess.PIPE附加到調用的stdin。 – TimD

+0

@TimD:除非您在進程運行時讀/寫/關閉相應的管道,否則不要使用PIPE,即不要在subprocess.call()函數中使用它,即使它恰好與某些ffmpeg可執行文件的參數。 – jfs

-1

從Python /子/調用文檔:

等待命令完成,然後返回返回碼屬性。

所以只要你調用的進程沒有退出,你的程序就不會繼續。

您應該設置一個Popen進程對象,將其標準輸出和錯誤放入不同的緩衝區/流中,並且在出現錯誤時終止進程。

也許是這樣工作的:

proc = subprocess.Popen(args, stderr = subprocess.PIPE) # puts stderr into a new stream 
while proc.poll() is None: 
    try: 
     err = proc.stderr.read() 
    except: continue 
    else: 
     if err: 
      proc.terminate() 
      break 
+0

你真的看過我的問題嗎?你一直沒有回答我問的問題。 – TimD

0

我喜歡用commands模塊。在我看來,使用起來更簡單。

import commands 
cmd = "ffmpeg -y -i %s -ss 0 -t 20 %s 2>&1" % (inf, outf) 
status, output = commands.getstatusoutput(cmd) 
if status != 0: 
    raise Exception(output) 

作爲一個側面說明,有時路徑可以是一個問題,你可能想使用絕對路徑FFmpeg的二進制文件。

[email protected]:~$ which ffmpeg 
/opt/local/bin/ffmpeg