我有一個相當大的Python項目,當前在Linux上運行,但我試圖擴展到Windows。我已經將代碼縮減爲可以運行以說明我的問題的完整示例:我有兩個類,Parent和Child。家長首先被初始化,創建一個記錄器,併產生一個子做的工作:在Windows中使用多處理功能進行Python日誌記錄
import logging
import logging.config
import multiprocessing
class Parent(object):
def __init__(self, logconfig):
logging.config.dictConfig(logconfig)
self.logger = logging.getLogger(__name__)
def spawnChild(self):
self.logger.info('One')
c = Child(self.logger)
c.start()
class Child(multiprocessing.Process):
def __init__(self, logger):
multiprocessing.Process.__init__(self)
self.logger = logger
def run(self):
self.logger.info('Two')
if __name__ == '__main__':
p = Parent({
'version':1,
"handlers": {
"console": {
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
},
},
"root": {
"level": "DEBUG",
"handlers": [
"console",
]
}
}
)
p.spawnChild()
在Linux(具體而言,Ubuntu的12.04),我得到以下(預期)輸出:
[email protected]:~$ python test.py
One
Two
但在Windows(具體地,視窗7),它失敗酸洗錯誤:
C:\>python test.py
<snip>
pickle.PicklingError: Can't pickle <type 'thread.lock'>: it's not found as thread.lock
的問題歸結爲Windows的缺乏真正的叉的,所以對象具有線程之間發送時,進行酸洗。但是,記錄器不能被醃製。我已經使用__getstate__和__setstate__避免兒童酸洗和參考的名字嘗試:
def __getstate__(self):
d = self.__dict__.copy()
if 'logger' in d.keys():
d['logger'] = d['logger'].name
return d
def __setstate__(self, d):
if 'logger' in d.keys():
d['logger'] = logging.getLogger(d['logger'])
self.__dict__.update(d)
這就像以前一樣工作在Linux和現在的Windows不會失敗與PicklingError。然而,我的產量也只有從父:
C:\>python test.py
One
C:\>
看來,孩子是無法使用記錄儀,儘管沒有消息抱怨「沒有記錄可以發現處理‘__main__’」或任何其他錯誤消息。我環顧四周,我有辦法徹底改變我登錄程序的方式,但這顯然是最後的手段。我希望我只是錯過了一些明顯的東西,而且人羣的智慧可以向我指出。
'如果some_dict.keys()中的鍵正好是執行該檢查的錯誤方式。它在python2中花費O(n)時間。只需使用'if key in some_dict'。關於你的問題。子進程可能有不同的標準輸出,因此你看不到輸出。嘗試添加文件處理程序並檢查文件中的輸出是否正確。 – Bakuriu 2014-10-02 19:25:45
欣賞關於該鍵的註釋,該註釋剛剛從另一個SO帖子複製以進行測試。 我所有的實際日誌都是在文件中完成的,問題仍然存在。對於創建上述腳本,stdout更容易測試。使用 「multi_file_handler」:{ 「類」: 「logging.handlers.RotatingFileHandler」, 「文件名」: 「output.log」 }, 導致了同樣的問題 - 在Linux上 「一\ nTwo」,「一「在窗口 – user2093082 2014-10-02 19:31:38
問題可能是,通常不會調用'__init__'時取消調用。這意味着子進程沒有*調用'logging.config.dictConfig(...)',因此它可能使用默認配置。嘗試改變'__setstate__'方法,以便使用正確的設置調用'dictConfig'並查看是否有更改。 – Bakuriu 2014-10-02 19:35:47