NB. Я видел Выход журнала многопроцессорной обработки. Процесс - к сожалению, он не отвечает на этот вопрос.
Я создаю дочерний процесс (в Windows) с помощью многопроцессорной обработки. Я хочу, чтобы все вывода stdout и stderr дочернего процесса были перенаправлены в файл журнала, а не появлялись на консоли. Единственное предложение, которое я видел, это для дочернего процесса установить sys.stdout в файл. Однако это не позволяет эффективно перенаправить весь вывод stdout из-за поведения перенаправления stdout в Windows.
Чтобы проиллюстрировать проблему, создайте 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()
Чтобы увидеть то же поведение, что и у меня, вероятно, необходимо, чтобы DLL была построена с использованием другой среды выполнения C, чем та, которую использует Python. В моем случае 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 не смогла перенаправить вывод stdout, сгенерированный DLL. Это неудивительно, учитывая природу базовых API для перенаправления стандартного вывода в Windows. Я сталкивался с этой проблемой на родном уровне / C ++ и никогда не нашел способа надежно перенаправить стандартный вывод изнутри процесса. Это должно быть сделано извне.
Это на самом деле и есть причина, по которой я запускаю дочерний процесс - чтобы я мог подключаться к его каналам извне и, таким образом, гарантировать, что я перехватываю весь его вывод. Я определенно могу сделать это, запустив процесс вручную с помощью pywin32, но я бы очень хотел иметь возможность использовать средства многопроцессорности, в частности возможность общаться с дочерним процессом через многопроцессорный объект Pipe, чтобы получить прогресс обновления. Вопрос в том, существует ли какой-либо способ использовать многопроцессорную обработку для своих возможностей IPC и , чтобы надежно перенаправить весь вывод дочернего элемента stdout и stderr в файл.
ОБНОВЛЕНИЕ: Глядя на исходный код для многопроцессорной обработки. У процессов есть статический член _Popen, который выглядит так, как будто он может использоваться для переопределения класса, используемого для создания процесса. Если для него установлено значение «Нет» (по умолчанию), он использует multiprocessing.forking._Popen, но выглядит так:
multiprocessing.Process._Popen = MyPopenClass
Я мог бы отменить создание процесса. Однако, хотя я мог бы извлечь это из multiprocessing.forking._Popen, похоже, мне пришлось бы скопировать кучу внутренних вещей в мою реализацию, что звучит странно и не очень перспективно для будущего. Если это единственный выбор, я думаю, что я бы, пожалуй, был полон решимости сделать все вручную с помощью pywin32.