注意。我見過Log output of multiprocessing.Process - 不幸的是,它沒有回答這個問題。Python多處理:我如何可靠地重定向來自子進程的標準輸出?
我正在通過多處理創建一個子進程(在Windows上)。我想所有的子進程的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;
}
}
然後創建並運行類似以下,其中進口該DLL並調用函數的Python腳本:
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()
爲了看到和我一樣的行爲,可能需要針對不同於C++運行時的C運行時構建DLL。就我而言,蟒蛇是建立與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的性質,這並不令人驚訝。我以前在native/C++級別遇到過這個問題,並且從來沒有找到一種方法可以在進程內可靠地重定向stdout。它必須在外部完成。
這實際上是我啓動子進程的原因 - 這樣我可以將外部連接到它的管道,從而保證我攔截它的所有輸出。我可以通過使用pywin32手動啓動該過程來完成此任務,但我非常希望能夠使用多處理功能,特別是通過多處理Pipe對象與子進程進行通信的能力,以獲得進度更新。問題是,是否有任何方法可以使用多處理技術爲其IPC工廠和將子級的所有stdout和stderr輸出可靠地重定向到文件。
UPDATE:看爲multiprocessing.Processs的源代碼,它具有一個靜止構件,_popen,它看起來像它可以被用於覆蓋用於創建過程的類。如果設置爲none(默認值),它採用了multiprocessing.forking._Popen,但它說
multiprocessing.Process._Popen = MyPopenClass
我可以覆蓋進程創建的模樣。但是,儘管我可以從multiprocessing.forking.Popen中得到這個結果,但是看起來我必須將一堆內部的東西複製到我的實現中,這聽起來很片面,而且不是很有前途。如果這是唯一的選擇,我想我可能會用pywin32來手動完成整個事情。
您可以使用Win32 API來啓動子進程,還是必須使用現有的Python庫來完成? –
是的,我在問題中提到「我可以通過使用pywin32手動啓動該過程來完成此操作」。放棄更高級別,獨立於平臺的多處理模塊似乎是一種恥辱,因爲似乎缺少一些功能缺失的功能 - 爲孩子指定stdin/stdout句柄的能力。 – Tom
我正在採用的方法(除非有人提出了更好的選擇)是通過子進程模塊啓動進程,並將stdin/stdout重定向到文件,並使用本機Windows命名管道進行進程通信。 – Tom