首页 > 解决方案 > 有没有办法运行在 Python 中在后台打开一个窗口的子进程?

问题描述

我正在尝试ffplay使用subprocess. 当ffplay被调用时,它会打开一个带有视频的窗口并将信息输出到控制台,直到窗口关闭。我想在视频继续播放时抓取输出并返回到 Python 脚本(即,不关闭窗口)。

目前,我有:

# some code
subprocess.call(['ffplay', 'video.mp4'])
# some more code

如何更改此代码以保持窗口打开并将进程输出发送到后台以继续 Python 脚本?

提前致谢!

标签: pythonffmpegsubprocessffplay

解决方案


我认为Popen是您正在寻找的。

这是一个代码示例:

import subprocess
import time

process = subprocess.Popen(['ffplay', '-hide_banner', '-nostats', '-autoexit', 'video.mp4'])

for i in range(10):
    time.sleep(1)
    print('Continue running ' + str(i))

process.wait()

subprocess.Popen打开一个新的子进程,子子进程在后台执行。
Python 脚本在subprocess.Popen.

您可以等待子流程完成,或终止它(或让它运行)。


抓取stdoutstderr输出的示例(将 FFplay 输出读取到 Python 的内存中)。

import subprocess
import time

process = subprocess.Popen(['ffplay', '-autoexit', '-t', '1', 'video.mp4'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

stdout, stderr = process.communicate()

process.wait()

print('stdout = ' + stdout.decode('utf-8'))
print('stderr = ' + stderr.decode('utf-8'))

在执行其他操作时“在飞行中”读取 FFplay 统计信息需要一个线程。
在 Windows 中,看起来我们需要从stderr.
readline()不起作用,因为 FFplay 输出行以 LF ( \r) 字符结尾。

这是一个代码示例:

import subprocess
import threading

# Read from stderr pipe - "draining the stderr pipe"
def drain_pipe(a_process):
    output_txt = b''
    while a_process.poll() is None:
        try:
            # Read one byte at a time, it's the only way it works in Windows, because lines ends with just \r.
            a_char = a_process.stderr.read(1)
            output_txt += a_char
            if a_char == b'\r':  # Look for line feed character.
                print(output_txt.decode('utf-8'))
                output_txt = b''
        except:
            break  # Exception may be raised because the pipe closes asynchronous

process = subprocess.Popen(['ffplay', '-stats', '-autoexit', 'video.mp4'], stderr=subprocess.PIPE)

stderr_thread = threading.Thread(target=drain_pipe, args=(process,))  # Create a thread for reading from stderr
stderr_thread.start()  # Start thread

# some more code...

process.wait()
stderr_thread.join()  # Join thread

推荐阅读