21 Stimmen

Terminaltext wird nach Beendigung des Unterprozesses unsichtbar

Nach Beendigung eines ffmpeg Subprozess, gerät das Terminal durcheinander - getippte Zeichen sind unsichtbar! Die Eingabe funktioniert zwar noch, da Befehle ausgeführt werden können, aber die Tastatureingabe wird nicht an das Terminal zurückgesendet.

Shell-Befehl ausgeben reset setzt alles wieder in den Normalzustand zurück (oder !reset von ipython aus), so dass ein Workaround das Problem durch den Aufruf von os.system('reset') innerhalb des Skripts.

Andere Dinge, die ich ausprobiert habe: import curses; curses.initscr() bevor der Unterprozess gestartet wird und curses.endwin() nach der Beendigung, was zwar einigermaßen funktionierte, aber andere Dinge kaputt machte. Ein weiteres Problem, das möglicherweise damit zusammenhängt, ist, dass das interaktive Terminal nach dem Starten des Kindprozesses verzögert wird und manchmal die eingegebenen Zeichen nicht erfasst.

Der Code zum Starten des Prozesses sieht folgendermaßen aus:

with open('/tmp/stdout.log', 'w') as o:
    with open('/tmp/stderr.log', 'w') as e:
        proc = subprocess.Popen([args], stdout=o, stderr=e)

Und später, um sie zu stoppen:

proc.terminate()
proc.communicate()

Was könnte hier schiefgehen?

0voto

J.Z. Punkte 779

10 Jahre später bin ich auf das gleiche Problem gestoßen (Mac, Python 3.8.2).

Per diese SO-Antwort Ich bin dazu übergegangen, Popen als Kontextmanager zu verwenden, was sicherstellt, dass ffmpeg alle seine Handles korrekt freigibt.

def raw_start_times(in_filename, silence_threshold, silence_duration, start_ms = 0, end_ms = 200 * 1000):
    """Given an in_filename, find possible split points (phrase start
    times) using ffmpeg.

    Note that potential phrase start times are actually when any
    silence in the clip *ends*.
    """

    timematch = r'(?P<deltafromstart>[0-9]+(\.?[0-9]*))'
    end_re = re.compile(f'silence_end: {timematch} ')

    # The time returned is the deltafromstart; i.e., the actual
    # time is the start_ms + the delta.
    def time_ms(m):
        return start_ms + round(float(m.group('deltafromstart')) * 1000)

    # ffmpeg outputs e.g. "silence_end: 123.234" to stderr.
    def add_if_matches_end_re(line, arr):
        s = line.decode('utf-8').strip()
        end_match = end_re.search(s)
        if end_match:
            arr.append(time_ms(end_match))

    ffmpegcmd = (
        ffmpeg
        .input(in_filename, ss=(start_ms/1000.0), t=(end_ms-start_ms)/1000.0)
        .filter('silencedetect', n='{}dB'.format(silence_threshold), d=silence_duration)
        .output('-', format='null')
        .compile()
    ) + ['-nostats']  # FIXME: use .nostats() once it's implemented in ffmpeg-python.
    logger.debug(f'Running command: {subprocess.list2cmdline(ffmpegcmd)}')

    chunk_starts = [start_ms]
    with subprocess.Popen(
            ffmpegcmd,
            stderr=subprocess.PIPE,
            stdout = subprocess.PIPE) as p:
        for line in p.stderr:
            add_if_matches_end_re(line, chunk_starts)
    return chunk_starts

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X