2014-02-13 39 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

相关问题