通过多处理获取函数的标准输出

Vla*_*ecs 4 python

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

对该函数的调用成本非常高,需要几分钟才能完成。为了加快计算速度,我使用 Python 多处理来并行运行该函数。现在的问题是如何区分每个worker的stdout?

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

注意:我无法控制写入标准输出的函数。

aba*_*ert 5

假设您为每个任务使用单独的任务Process(这有缺点\xe2\x80\x94,例如,一次运行 200 个任务通常会比一次运行 8 个任务慢,尤其是当您使用像 Windows 这样的平台,进程生成有点昂贵\xe2\x80\x94,但可能值得),这并不难做到。

\n\n

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

\n\n

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

\n\n

例如:

\n\n
tempdir = tempfile.mkdtemp()\n\ndef wrap(task, name):\n    def wrapper(*args, **kwargs):\n        with open(os.path.join(tempdir, name), \'w\') as f:\n            sys.stdout = f\n            task(*args, **kwargs)\n    return wrapper\n\nprocs = []\nfor i in range(8):\n    name = str(i)\n    proc = multiprocessing.Process(target=wrap(task, name), name=name, ...)\n    proc.start()\n    procs.append(proc)\nfor proc in procs:\n    proc.join()\n    with open(os.path.join(tempdir, proc.name)) as f:\n        do_stuff_with(f.read())\nshutil.rmtree(tempdir)\n
Run Code Online (Sandbox Code Playgroud)\n