2012-05-14 3 views
0

서브 프로세스와 출력을 읽는 시스템 명령을 실행하려고합니다.파이썬 ffmpeg 서브 프로세스를 종료하면 cli 출력이 깨집니다.

그러나 명령에 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 인수와 시도했지만 뭔가를 놓친 적이 있습니다. 그냥 내가 여기서 간단하게 할거라 생각 했어.

데비안 서버에서 실행 중입니다.

여기에 뭔가가 있습니까?

편집 : 지속적는 FFmpeg 프로세스를 죽일 때 이것은 단지의 경우와 같다 ​​

. ffmpeg 프로세스가 10 초 전에 정상적으로 종료되면 아무런 문제가 없습니다.

출력을 인쇄하는 사람, 사람이없는 사람, ffmpeg 명령을 사용하여 파일의 무결성을 검사하는 데 10 초 이상 걸리는 다른 명령을 실행 해 보았습니다.

저는 ffmpeg가 \ r을 사용하여 인쇄하고 strerr 파이프의 모든 것을 인쇄한다고 생각합니다. 이것이 원인 일 수 있습니까? 어떤 아이디어로 그것을 고치는 법?

답변

1

음. 귀하의 코드는 확실히 내 우분투 서버에서 잘 작동합니다.

난 당신의 코드를 테스트 할 수 있도록 내가 몇 줄을 추가 (내 생각 가까운 사촌 데비안의 동생 인).

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--------------------------" 

매력처럼 작동합니다.

이 코드는 서버에서 작동하는 경우

, 나는 문제가 실제로 데이터를 검색하려고

명령 줄 응용 프로그램에 놓여 같아요.

+0

Thx Ryan, 네 말이 맞아. 이것은 진행중인 ffmpeg 프로세스를 죽이는 경우에만 해당하는 것 같습니다. 내 편집을 참조하십시오. – JayLev

0

동일한 문제가 있습니다. 나는 실행중인 FFmpeg을 정상적으로 파이썬 서브 프로세스에서 종료 할 수 없기 때문에 <process>.kill()을 사용하고있다.그러나 이것은 FFmpeg가 tty의 모드를 제대로 복원하지 못한다는 것을 의미한다고 생각합니다. (https://askubuntu.com/a/172747)

bash 프롬프트에서 reset을 실행하여 쉘을 다시 얻을 수 있지만 화면을 지울 수 없으므로 계속 작업하면서 스크립트의 출력을보십시오.

stty echo을 실행하면 쉘 세션에서 에코가 다시 발생하는 것이 좋습니다.

FFmpeg를 마친 후에도 스크립트에서 실행할 수 있습니다. 나는하고있다 :

ffmpeg_popen.kill() 
ffmpeg_popen.wait() 
subprocess.call(["stty", "echo"]) 

이것은 나의 쉘로 bash를 가진 우분투에서 나를 위해 일한다. YMMV,하지만 도움이되기를 바랍니다. 그것은 hacky 냄새가 있지만 그것은 내가 찾은 최고의 솔루션입니다.

0

ffmpeg에서 비슷한 문제가 발생했습니다. Popen.kill()을 사용하여 ffmpeg를 종료하면 제대로 닫히지 않고 터미널에서 반향을 복원하지 않는 것 같습니다.

우리는이 표준 입력 파이프를 사용하여 해결할 수 있습니다, 우리는 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가 정상적으로 종료되지 모르겠어요. 아마도 처음에는이 버그의 원인과 관련이있을 것입니다.

관련 문제