2015-11-11 21 views
0

我正在处理一个多处理示例(An introduction to parallel programming)。我修改了Pool Class示例以满足我的特定需求 - 将一束栅格与研究区多边形平行剪切。另一方面,脚本完成并打印“处理完成”。不利的一面是,没有产生输出。我怀疑我在`pool.apply_async'函数中有一些程序错误。为什么这个脚本没有产生任何结果?如何并行剪切光栅?

import arcpy, os 
import multiprocessing as mp 

arcpy.env.workspace = r'F:\temp\inws' 
outws_utm11 = r'F:\temp\outws' 
clipper_utm11 = r'F:\temp\some_polygon.shp' 

rasters = arcpy.ListRasters() 

pool = mp.Pool(processes=4) 

def clip_raster(clipper, outws, raster): 
     arcpy.Clip_management(raster, "#", os.path.join(outws, raster), clipper, nodata_value = 0, clipping_geometry = "ClippingGeometry") 

[pool.apply_async(clip_raster, args=(clipper_utm11,outws_utm11, ras)) for ras in rasters] 

print "Processing complete." 

回答

2

apply_async功能揭开序幕的功能在一个工作进程,但直到函数完成不会阻止。你让主流程完成并退出,而不是等待工人完成。这会导致他们被杀害,这可能会在他们创造你的输出之前发生。

由于您只是将相同的功能应用于rasters列表中的所有项目,因此应考虑使用pool.map来代替。它将接受函数名称和可迭代对象作为其参数,并在列表中的每个项目上调用该函数。所有这些函数调用都将发生在池中的工作进程中。 pool.map函数的一个注意事项是,您传递的函数对象只能接受一个参数:列表中的项目。我看到您的clip_rasters函数使用了其他一些参数,因此在下面的示例中,我使用functools.partial创建了clip_raster的新版本,即总是包括前两个参数。这个绑定到它的clipper_utm11outws_utm11的新函数现在可以与pool.map一起使用。

import arcpy, os 
import functools 
import multiprocessing as mp 

arcpy.env.workspace = r'F:\temp\inws' 
outws_utm11 = r'F:\temp\outws' 
clipper_utm11 = r'F:\temp\some_polygon.shp' 

rasters = arcpy.ListRasters() 

pool = mp.Pool(processes=4) 

def clip_raster(clipper, outws, raster): 
     arcpy.Clip_management(raster, "#", os.path.join(outws, raster), clipper, nodata_value = 0, clipping_geometry = "ClippingGeometry") 

bound_clip_raster = functools.partial(clip_raster, clipper_utm11, outws_utm11) 
results = pool.map(bound_clip_raster, rasters) 

print "Processing complete." 

该代码会在你rasters列表一次为每个项目的调用bound_clip_raster功能,包括clipper_utm11outws_utm11。所有结果都将在名为results的列表中提供,并且pool.map的呼叫处于阻塞状态,因此主流程将等待所有工作人员完成后才能退出。

如果出于某种奇怪的原因您打算使用apply_async,那么您需要在脚本末尾添加一些代码以使用对象的关联方法阻止主进程,直到它们可以完成,例如wait(),或者通过调用ready()来轮询完成。但你应该真的使用pool.map这个用例。这是它的目的。

+0

我很欣赏这个解释。这是有道理的,尽管看起来代码将CPU限制在〜35%左右,并且挂在那里。没有输出产生。我想知道这是否可能是由于'clip_raster()'函数中一个未定义的'raster'变量造成的?我不确定代码如何将'rasters'列表中的项目并行传递给函数? – Borealis

+1

您是否确认过您的'clip_raster'函数实际上只能在一个项目上正常工作,而无需首先使用任何多处理?如果你已经这样做了,试着将函数的整个主体封装在一个try/except块中,它捕获所有的异常并将一个回溯写入一个文件。如果创建了一个文件,那么你知道你的函数抛出异常,并且文件中的回溯应该指向它。 – skrrgwasme