首页 > 解决方案 > 多次调用后,Python 子进程模块管道停止使用 Apache Beam

问题描述

我正在使用 python 子进程模块从 MacOS 上的 Apache Beam DoFn 运行子进程。

前几个子进程调用工作正常,但是在大约第 7 个子进程调用时,我开始收到错误:

OSError: [Errno 9] Bad file descriptor

从子流程模块中。

我尝试更改正在读取/管道的文件,但这不会影响产生的错误。

我尝试将问题隔离到以下代码,但这运行正常:

import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptions
from subprocess import run, PIPE
import io

def run_subprocess(element):
    x = run(["ffmpeg", "-loglevel", "panic", "-t", '900', "-f", "mp3", "-i", "pipe:0", "-map_metadata", "-1", "-vn", "-acodec", 'pcm_s16le', "-ac",
            '2', "-ar", '44100', "-f", "wav", 'pipe:1'], input=element.read(), capture_output=True)
    yield x.stdout[:20]

def open_file(element):
    with open(element, 'rb') as f:
        data = io.BytesIO(f.read())
    data.seek(0)
    yield data

with beam.Pipeline(options=PipelineOptions()) as p:
    _ = (p
    | "A" >> beam.Create(['./test.mp3']*100)
    | "B" >> beam.ParDo(open_file)
    | "C" >> beam.ParDo(run_subprocess)
    | "D" >> beam.ParDo(print)
    )

与上面的示例相比,管道相对复杂,但失败的特定 DoFn 与run_subprocess上面非常相似。

我已经尝试在OSError那里捕获并设置测试子流程模块的其他用途。那时,即使只是运行subprocess.run(['echo'], input=b'hi', capture_output=True)Popen(['echo'], stdout=PIPE, stderr=PIPE, stdin=PIPE)引发相同的错误。但是,在Popen(['echo'])没有管道的情况下运行不会导致任何问题。

知道这里发生了什么吗?Apache Beam 使用的管道和子进程使用的管道之间是否存在一些干扰?或者也许对管道使用/缓冲区大小有一些系统级别的限制?

标签: pythonmacossubprocesspipeapache-beam

解决方案


推荐阅读