Python:管道化子流程的大型标准输出时的奇怪挂起行为

Python:管道化子流程的大型标准输出时的奇怪挂起行为,python,ffmpeg,subprocess,pipe,stdout,Python,Ffmpeg,Subprocess,Pipe,Stdout,我目前正在调用ffmpeg从视频文件中提取二进制数据流,然后将该二进制数据放入列表中。这个数据流中有很多数据,大约4000 kb。这是密码 # write and call ffmpeg command, piping stdout cmd = "ffmpeg -i video.mpg -map 0:1 -c copy -f data -" proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) # read from stdout, byte

我目前正在调用
ffmpeg
从视频文件中提取二进制数据流,然后将该二进制数据放入列表中。这个数据流中有很多数据,大约4000 kb。这是密码

# write and call ffmpeg command, piping stdout
cmd = "ffmpeg -i video.mpg -map 0:1 -c copy -f data -"
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)

# read from stdout, byte by byte
li = []
for char in iter(lambda: proc.stdout.read(1), ""):
    li.append(char)
这个很好用。但是,如果我从
stdout
中取出正在读取的部分,它将开始工作,但随后挂起:

cmd = "ffmpeg -i video.mpg -map 0:1 -c copy -f data -"
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
time.sleep(10)
我必须在末尾添加
时间。sleep(10)
,否则进程将在
子进程之前结束,导致此错误:

av_interleaved_write_frame(): Invalid argument
Error writing trailer of pipe:: Invalid argument
size=       0kB time=00:00:00.00 bitrate=N/A speed=N/A
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing ove
rhead: 0.000000%
Conversion failed!
调用
subprocess.call(cmd,stdout=subprocess.PIPE)
subprocess.call(cmd)
也会导致挂起(后者仅在控制台中显示
stdout
,而前者不显示)

stdout
读取是否有什么东西可以防止这种挂起(比如缓冲区可能被清除),或者我是否在不知不觉中在其他地方引入了一个bug?我担心这么小的改动会导致程序崩溃;这并不能激发很多信心

这段代码的另一个问题是,我需要从另一个线程的列表中读取。这可能意味着我需要使用
队列
。但是当我执行下面的代码时,它需要11秒,而列表中的代码需要3秒:

cmd = "ffmpeg -i video.mpg -loglevel panic -hide_banner -map 0:1 -c copy -f data -"
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)

q = Queue()

for char in iter(lambda: proc.stdout.read(1), ""):
    q.put(char)
我应该使用另一个数据结构吗

  • 从管道中一次读取一个字节的数据是非常低效的。你应该读更多的内容

  • 正如您所注意到的,执行子进程,然后在不等待子进程完成的情况下终止父进程将导致管道中断错误,并且子进程将失败

  • 调用
    subprocess.call(cmd,stdout=subprocess.PIPE)
    将在操作系统缓冲区被填满时阻止/暂停写入程序(即,如果您没有像本例中那样从管道读取数据)

  • 队列
    只要一次不读取一个字节就可以了


  • 不确定,但尝试添加选项-nostdinGood idea以添加-nostdin,因为它是一个子流程。但是,我没有解决这个问题,我一次读一个字节的原因是因为我一次解码一个字节的数据。我会想一个更好的办法。