2014-02-13 40 views
1

我目前有18個函數對大型XML文件執行不同的驗證集。我創建了一個定製ValidationWarning類,它擴展了UserWarning,並且這些函數爲每個驗證失敗提出警告。最後,我需要生成包含所有故障的XLSX報告(每個故障的識別信息可在ValidationWarning對象中找到)。我計劃爲每個函數產生一個進程(我看到了任務放在JoinableQueue中的例子,但我不明白爲什麼這是必須的,除非任務列表稍後會被修改)。驗證失敗的順序是不相關的,在所有驗證完成之前,我不需要看到結果。我是否應該將showwarning()函數替換爲每個驗證函數以寫入Manager()返回的list?加入所有進程後,我可以將結果導出到XLSX。這比寫信給Queue好嗎? Queue可能會更快,但結果寫入不是瓶頸,我不明白,我怎麼會解決以下問題(見http://docs.python.org/2/library/multiprocessing.html#programming-guidelines):如何將結果報告給多個進程的主進程?

這意味着,無論你使用一個隊列,你需要確保已經放入隊列的所有項目在加入之前最終都會被刪除。否則,您無法確定將項目放入隊列的進程將終止。

有沒有更好的方法,我忽略了?據我的理解,我不能在主進程中使用上下文管理器,並期望它能夠捕獲來自每個驗證進程的警告,儘管我還沒有對它進行測試(編輯:我測試了它,並且如預期的那樣,它失敗了)。直接寫入XLSX而不是首先獲得所有結果也聽起來很困難,因爲我需要創建一個空白的XLSX文件並在管理對共享XLSX文件的訪問的同時在每個進程中進行更新。

謝謝!

+1

你看過'multiprocessing.Pool'嗎? – User

+0

'Pool'不在我閱讀的教程中(http://pymotw.com/2/multiprocessing/),所以我直到你提到它才知道它。從概念上講,「Pool」對我來說很有意義 - 修改每個驗證函數以返回失敗列表,並在結果可用時聚合列表。然而,當我不能使用'catch_warnings'([它不是線程安全的](http://docs.python.org/2/)時,我怎麼在每個驗證函數中將警告寫入局部變量庫/ warnings.html#warnings.catch_warnings))?我可以替換'showwarning()',但我沒有明確地調用它來選擇輸出列表。 – user1093967

+0

也許我太擔心'catch_warnings'。我一起入侵了一些難看的測試代碼(當我編寫我的真實代碼時,我會考慮使用'map_async'或另一種替代方法),嘗試觸發與替換和稍後恢復'showwarning()'相關的故障條件,但是我沒有。這是我的測試代碼,僅在Ideone上託管,因爲我的公司阻止了我所知的所有其他事情,即使Ideone不支持'multiprocessing':http:// ideone。com/OQBxHL 我仍然非常害怕違背文檔,除非我將線程安全與流程的不同概念混淆...... – user1093967

回答

1

我在同一家公司上班,看到你的郵件,公司郵件列表:)

你爲什麼不嘗試這樣的:

from multiprocessing import Pool 
from time import sleep 
import warnings 

def catchwarnings(arg): 
    msg, num = arg 
    with warnings.catch_warnings(record=True) as w: 
     if num == 4: 
      sleep(10) 
     print 'catchfxn called with num=%d' % num 
     warnings.simplefilter("always") 

     # Trigger a warning. 
     for i in xrange(num): 
      warnings.warn("{} - #{}".format(msg, i), UserWarning) 
    return w 

def printwarnings(w): 
    print w 

if __name__=='__main__': 
    p = Pool(18) 
    for i in [('waaa', 3), ('squeee', 4), ('maaaa', 2)]: 
     p.apply_async(catchwarnings, args=(i,), callback=printwarnings) 
    p.close() 
    p.join() 

給出了這樣的:

catchfxn called with num=3 
catchfxn called with num=2 
[<warnings.WarningMessage object at 0x10559a4d0>, <warnings.WarningMessage object at 0x10559a710>, <warnings.WarningMessage object at 0x10559a750>] 
[<warnings.WarningMessage object at 0x10559a510>, <warnings.WarningMessage object at 0x10559a550>] 
catchfxn called with num=4 
[<warnings.WarningMessage object at 0x10559a650>, <warnings.WarningMessage object at 0x10559a690>, <warnings.WarningMessage object at 0x10559a4d0>, <warnings.WarningMessage object at 0x10559a710>] 

使用回調代碼是一個小清潔。

+0

感謝您使用回調的示例。我很欣賞使用squeee。 :)我打算實施類似的包裝,就像你做的一樣,但我會研究一些基於地圖的替代方案是如何工作的。正如我在內部對Zsolt的回覆中所提到的,我對catch_warnings感到擔憂,但我會放棄它,因爲我在實踐中看不到問題。 – user1093967

相關問題