Multiprocesamiento de Python: ¿Cómo puedo redirigir CONFIABLEMENTE stdout desde un proceso secundario?

NÓTESE BIEN. He visto Salida de registro de multiprocesamiento. Proceso - desafortunadamente, no responde esta pregunta.

Estoy creando un proceso hijo (en Windows) a través del multiprocesamiento. Quierotodo de la salida stdout y stderr del proceso secundario para redirigirse a un archivo de registro, en lugar de aparecer en la consola. La única sugerencia que he visto es que el proceso secundario establezca sys.stdout en un archivo. Sin embargo, esto no redirige efectivamente toda la salida estándar, debido al comportamiento de la redirección estándar en Windows.

Para ilustrar el problema, cree una DLL de Windows con el siguiente código

#include <iostream>

extern "C"
{
    __declspec(dllexport) void writeToStdOut()
    {
        std::cout << "Writing to STDOUT from test DLL" << std::endl;
    }
}

uego, cree y ejecute un script de Python como el siguiente, que importa esta DLL y llama a la función:

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()

Para ver el mismo comportamiento que yo, probablemente sea necesario que la DLL se compile en un tiempo de ejecución C diferente al que usa Python. En mi caso, Python se compila con Visual Studio 2010, pero mi DLL se construye con VS 2005.

El comportamiento que veo es que la consola muestra:

> stdout_test.py

Writing to STDOUT from python, before redirect

Writing to STDOUT from test DLL

Mientras el archivo stdout_redirect_log.txt termina conteniendo:

Writing to STDOUT from python, after redirect

En otras palabras, la configuración de sys.stdout no pudo redirigir la salida stdout generada por la DLL. Esto no es sorprendente dada la naturaleza de las API subyacentes para la redirección stdout en Windows. He encontrado este problema en el nivel nativo / C ++ antes y nunca encontré una manera de redirigir de manera confiable stdout desde un proceso. Tiene que hacerse externamente.

Esta es realmente la razón por la que estoy iniciando un proceso secundario: es para poder conectarme externamente a sus tuberías y garantizar así que estoy interceptando toda su salida. Definitivamente puedo hacer esto iniciando el proceso manualmente con pywin32, pero me gustaría poder utilizar las facilidades de multiprocesamiento, en particular la capacidad de comunicarse con el proceso secundario a través de un objeto Pipe multiprocesamiento, para avanzar actualizaciones La pregunta es si hay alguna forma de utilizar el multiprocesamiento para sus instalaciones de IPC para redirigir de manera confiable toda la salida stdout y stderr del niño a un archivo.

ACTUALIZAR Mirando el código fuente para multiprocesamiento. Procesos, tiene un miembro estático, _Popen, que parece que puede usarse para anular la clase utilizada para crear el proceso. Si se establece en Ninguno (predeterminado), utiliza un multiprocesamiento.forking._Popen, pero parece decir

multiprocessing.Process._Popen = MyPopenClass

Podría anular la creación del proceso. Sin embargo, aunque podría derivar esto de multiprocessing.forking._Popen, parece que tendría que copiar un montón de cosas internas en mi implementación, lo que suena escaso y no está preparado para el futuro. Si esa es la única opción, creo que probablemente estaría dispuesto a hacer todo esto manualmente con pywin32.

Respuestas a la pregunta(4)

Su respuesta a la pregunta