注意。我见过multiprocessing.Process 的日志输出 https://stackoverflow.com/questions/1501651/log-output-of-multiprocessing-process- 不幸的是,它没有回答这个问题。
我正在通过多处理创建一个子进程(在 Windows 上)。我想all子进程的 stdout 和 stderr 输出被重定向到日志文件,而不是出现在控制台上。我看到的唯一建议是让子进程将 sys.stdout 设置为文件。但是,由于 Windows 上的 stdout 重定向行为,这并不能有效地重定向所有 stdout 输出。
为了说明问题,使用以下代码构建一个 Windows DLL
#include <iostream>
extern "C"
{
__declspec(dllexport) void writeToStdOut()
{
std::cout << "Writing to STDOUT from test DLL" << std::endl;
}
}
然后创建并运行如下所示的 python 脚本,该脚本导入此 DLL 并调用该函数:
from ctypes import *
import sys
print
print "Writing to STDOUT from python, before redirect"
print
sys.stdout = open("stdout_redirect_log.txt", "w")
print "Writing to STDOUT from python, after redirect"
testdll = CDLL("Release/stdout_test.dll")
testdll.writeToStdOut()
为了看到与我相同的行为,可能需要针对与 Python 使用的不同的 C 运行时来构建 DLL。就我而言,python 是使用 Visual Studio 2010 构建的,但我的 DLL 是使用 VS 2005 构建的。
我看到的行为是控制台显示:
> stdout_test.py
Writing to STDOUT from python, before redirect
Writing to STDOUT from test DLL
虽然文件 stdout_redirect_log.txt 最终包含:
Writing to STDOUT from python, after redirect
换句话说,设置 sys.stdout 无法重定向 DLL 生成的 stdout 输出。考虑到 Windows 中标准输出重定向的底层 API 的性质,这并不奇怪。我之前在本机/C++ 级别遇到过这个问题,但从未找到一种方法来可靠地从进程内重定向 stdout。它必须在外部完成。
这实际上就是我启动子进程的原因 - 这样我就可以从外部连接到它的管道,从而保证我拦截它的所有输出。我绝对可以通过使用 pywin32 手动启动进程来做到这一点,但我非常希望能够使用多处理的设施,特别是通过多处理 Pipe 对象与子进程通信的能力,以便取得进展更新。问题是是否有任何方法可以为其 IPC 设施使用多处理and可靠地将子进程的所有 stdout 和 stderr 输出重定向到文件。
UPDATE:查看 multiprocessing.Processs 的源代码,它有一个静态成员 _Popen,看起来可以用来重写用于创建进程的类。如果它设置为 None (默认),它会使用 multiprocessing.forking._Popen,但它看起来像这样说
multiprocessing.Process._Popen = MyPopenClass
我可以覆盖流程创建。然而,虽然我可以从 multiprocessing.forking._Popen 中得出这一点,但看起来我必须将一堆内部内容复制到我的实现中,这听起来很不稳定,而且不太面向未来。如果这是唯一的选择,我想我可能会选择使用 pywin32 手动完成整个事情。