[英]Killing python ffmpeg subprocess breaks cli output
我正在嘗試使用子進程執行系統命令並讀取輸出。
但是,如果命令花費了10秒鍾以上,我想殺死該子進程。
我嘗試了幾種方法。
我的最后一次嘗試是受此帖子啟發的: https : //stackoverflow.com/a/3326559/969208
例:
import os
import signal
from subprocess import Popen, PIPE
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
def pexec(args):
p = Popen(args, stdout=PIPE, stderr=PIPE)
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(10)
stdout = stderr = ''
try:
stdout, stderr = p.communicate()
signal.alarm(0)
except Alarm:
try:
os.kill(p.pid, signal.SIGKILL)
except:
pass
return (stdout, stderr)
問題是:程序退出后,cli中不會顯示任何字符,直到我按回車鍵為止。 爭取回報不會給我新的界限。
我想這與stdout和stderr管道有關。
我試過沖洗並從管道讀取(p.stdout.flush())
我也嘗試過使用不同的Popen參數,但可能會錯過一些東西。 只是以為我會在這里保持簡單。
我正在Debian服務器上運行它。
我在這里想念什么嗎?
編輯:
似乎只有在終止正在進行的ffmpeg進程時才如此。 如果ffmpeg進程在10秒之前正常退出,則完全沒有問題。
我嘗試執行幾個不同的命令,這些命令花費的時間超過10秒,其中一個輸出打印,一個不輸出,以及一個ffmpeg命令檢查文件的完整性。
args = ['sleep', '12s'] # Works fine
args = ['ls', '-R', '/var'] # Works fine, prints lots for a long time
args = ['ffmpeg', '-v', '1', '-i', 'large_file.mov','-f', 'null', '-'] # Breaks cli output
我相信ffmpeg使用\\ r打印並在strerr管道上打印所有內容。 這可能是原因嗎? 任何想法如何解決?
好。 您的代碼在我的Ubuntu服務器上肯定可以正常工作。
(我想這是Debian的近親或兄弟)
我增加了幾行,以便我可以測試您的代碼。
import os
import signal
from subprocess import Popen, PIPE
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
def pexec(args):
p = Popen(args, stdout=PIPE, stderr=PIPE)
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(1)
stderr = ''
try:
stdout, stderr = p.communicate()
signal.alarm(0)
except Alarm:
print "Done!"
try:
os.kill(p.pid, signal.SIGKILL)
except:
pass
return (stdout, stderr)
args = ('find', '/', '-name','*')
stdout = pexec(args)
print "----------------------result--------------------------"
print stdout
print "----------------------result--------------------------"
奇跡般有效。
如果此代碼在您的服務器上有效,我想問題實際上就在於
您嘗試檢索數據的命令行應用程序。
我也有同樣的問題。 我無法獲得運行中的FFmpeg來從python子<process>.kill()
正常終止,因此我正在使用<process>.kill()
。 但是我認為這意味着FFmpeg無法正確還原tty的模式(如此處所述: https : //askubuntu.com/a/172747 )
您可以通過在bash提示符處運行reset
恢復外殼,但這會清除屏幕,因此在繼續工作時看不到腳本的輸出。
更好的方法是運行stty echo
,以便在您的Shell會話中重新打開stty echo
。
對FFmpeg進行核對后,甚至可以在腳本中運行它。 我在做:
ffmpeg_popen.kill()
ffmpeg_popen.wait()
subprocess.call(["stty", "echo"])
這在bash作為shell的Ubuntu上對我有效。 YMMV,但希望對您有所幫助。 它聞起來很黑,但這是我找到的最好的解決方案。
我遇到了ffmpeg的類似問題。 看來,如果使用Popen.kill()將ffmpeg殺死,則無法正確關閉ffmpeg,也不會恢復終端上的回顯。
我們可以使用管道連接到stdin,然后像在cli會話中那樣寫q來關閉ffmpeg來解決此問題:
p = Popen(args, stdin=PIPE stdout=PIPE, stderr=PIPE)
p.stdin.write(b"q")
最好使用Popen.communicate以避免死鎖。 以下內容也將起作用:
p = Popen(args, stdin=PIPE stdout=PIPE, stderr=PIPE)
p.communicate(b'q')
但似乎甚至以下作品:
p = Popen(args, stdin=PIPE stdout=PIPE, stderr=PIPE)
p.kill()
我不確定是什么原因導致該ffmpeg干凈關閉,如果它具有輸入管道。 也許與最初導致此錯誤的原因有關?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.