NB. Я видел Log output of multiprocessing.Process - к сожалению, он не отвечает на этот вопрос.
Я создаю дочерний процесс (в окнах) через многопроцессорную обработку. Я хочу, чтобы все дочерние процессы stdout и stderr были перенаправлены в файл журнала, а не появлялись на консоли. Единственное, что я видел, - это для дочернего процесса установить sys.stdout в файл. Однако это не позволяет перенаправить весь вывод stdout из-за поведения перенаправления stdout в Windows.
Чтобы проиллюстрировать эту проблему, создайте DLL Windows со следующим кодом
#include <iostream>
extern "C"
{
__declspec(dllexport) void writeToStdOut()
{
std::cout << "Writing to STDOUT from test DLL" << std::endl;
}
}
Затем создайте и запустите python script следующим образом, который импортирует эту 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 для перенаправления stdout в Windows. Я столкнулся с этой проблемой на уровне native/С++ и никогда не нашел способ надежно перенаправить stdout изнутри процесса. Это должно быть сделано извне.
На самом деле это причина, по которой я запускаю дочерний процесс - это так, что я могу подключаться извне к его трубам и тем самым гарантировать, что я перехватываю весь его вывод. Я могу определенно сделать это, запустив процесс вручную с помощью pywin32, но мне очень хотелось бы иметь возможность использовать возможности многопроцессорности, в частности способность связываться с дочерним процессом через многопроцессорный объект Pipe, чтобы добиться прогресса обновления. Вопрос заключается в том, есть ли способ использовать многопроцессорность для своих объектов IPC и, чтобы надежно перенаправить все дочерние stdout и stderr в файл.
ОБНОВЛЕНИЕ:. Изучая исходный код для многопроцессорности. Процессы, он имеет статический член, _Popen, который выглядит так, как будто он может использоваться для переопределения класса, используемого для создания процесса. Если он установлен на None (по умолчанию), он использует multiprocessing.forking._Popen, но похоже, говоря
multiprocessing.Process._Popen = MyPopenClass
Я мог бы переопределить создание процесса. Однако, хотя я мог бы извлечь это из multiprocessing.forking._Popen, похоже, мне пришлось бы скопировать кучу внутренних вещей в мою реализацию, что звучит шероховато и не очень надежно для будущего. Если это единственный выбор, я думаю, что я, вероятно, мог бы сделать все это вручную с помощью pywin32.