使用多处理抓取函数的stdout

时间:2015-06-12 00:36:40

标签: python

我有一个Python函数,它接受一个参数并将许多文本行打印到stdout。我抓住了这个函数的标准输出并提取了相关信息。

对此功能的调用非常昂贵,需要几分钟才能完成。为了加速计算,我使用Python多处理来并行运行此函数。现在的问题是如何区分每个工人的标准输出?

跟踪每个工作人员输出到stdout的最简单方法是什么?我可以将每个worker输出重定向到某个文件描述符,然后在另一端读取每个文件描述符吗?

注意:我无法控制写入stdout的函数。

1 个答案:

答案 0 :(得分:4)

假设您为每项任务使用单独的Process(具有缺点 - 例如,一次运行200个任务通常比一次运行8个任务慢,特别是如果您在平台上像Windows一样,过程产生有点贵 - 但可能是值得的),这不是很难做到。

第一个关键是您必须替换子进程中的sys.stdout,而不是父进程。你在哪里可以做到的?您可以将Process子类化为run方法首先进行设置工作,然后调用超级run,或者可以将每个任务的函数包装在首先进行设置的函数中工作,然后调用真正的功能。

接下来,您可以用替换它?您可以将其写入由父进程传入的单独Pipe。而且,至少在Unix上,只需将sys.stdout设置为管道的写入端即可。但我不确定它是否适用于Windows。因此,如果您希望它是跨平台的(并且因为您不会告诉我您关心哪些平台,这似乎是必要的),写入文件很简单:

例如:

tempdir = tempfile.mkdtemp()

def wrap(task, name):
    def wrapper(*args, **kwargs):
        with open(os.path.join(tempdir, name), 'w') as f:
            sys.stdout = f
            task(*args, **kwargs)
    return wrapper

procs = []
for i in range(8):
    name = str(i)
    proc = multiprocessing.Process(target=wrap(task, name), name=name, ...)
    proc.start()
    procs.append(proc)
for proc in procs:
    proc.join()
    with open(os.path.join(tempdir, proc.name)) as f:
        do_stuff_with(f.read())
shutil.rmtree(tempdir)