我正在研究一个多处理示例(An introduction to parallel programming)。我修改了Pool Class示例以满足我的特定需求 - 用一个并行的研究区域多边形剪切一堆栅格。从好的方面来说,脚本完成并打印“Processing Complete”。在消极方面,没有产生输出。我怀疑我在`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."
答案 0 :(得分:2)
apply_async
函数在工作进程中启动函数,但在函数完成之前不会阻塞。您让主流程完成并退出,而不是等待工人完成。这会导致它们被杀死,这可能会在它们创建输出之前被破坏。
由于您只是将同一功能应用于rasters
列表中的所有项目,因此您应该考虑使用pool.map。它将接受函数名和可迭代对象作为其参数,并在列表中的每个项上调用该函数。所有这些函数调用都将在池中的工作进程中进行。但pool.map
函数的一个警告是,传递它的函数对象必须只接受一个参数:列表中的项。我看到您的clip_rasters
函数使用了其他几个参数,因此在下面的示例中,我使用functools.partial创建了clip_raster
的新版本始终< / em>包含前两个参数。这个绑定了clipper_utm11
和outws_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."
此代码会针对bound_clip_raster
列表中的每个项目调用rasters
函数,包括clipper_utm11
和outws_utm11
。所有结果都将在名为results
的列表中提供,并且对pool.map
的调用是阻塞的,因此主进程将等到所有工作人员完成后再退出。
如果由于某些奇怪的原因,您打算使用apply_async,那么您需要在脚本的末尾添加一些代码才能使用AsyncResult对象& #39;阻止主进程直到它们完成的相关方法,例如wait()
,或通过调用ready()
轮询完成循环。但是你真的应该使用pool.map
这个用例。这就是它的目的。
答案 1 :(得分:2)
我已经回答了一个可能对您也有用的问题。在这里看看:question
有一些好的做法,例如像您所做的那样将所有内容放入函数中,但必须要有一个main()
函数并被
if __name__ == '__main__':
main()
另一件事是此函数调用我在您的代码中插入的pool.apply_assync。
还进行了一些修改,因此您可以尝试一下,我已经测试过了,并且对我有用:
import arcpy, os
from multiprocessing import Pool
arcpy.env.workspace = r'C:\Gis\lab_geo\2236622'
outws_utm11 = r'C:\Gis\lab_geo\2236622\outs'
clipper_utm11 = r'C:\Gis\arcpy_teste\teste.shp'
rasters = arcpy.ListRasters()
def clipRaster(clipper, outws, raster):
arcpy.Clip_management(raster, "#", os.path.join(outws, raster), clipper, 0, "ClippingGeometry")
def clipRasterMulti(processList):
pool = Pool(processes=4, maxtasksperchild=10)
jobs= {}
for item in processList:
jobs[item[0]] = pool.apply_async(clipRaster, [x for x in item])
for item,result in jobs.items():
try:
result = result.get()
except Exception as e:
print(e)
pool.close()
pool.join()
def main():
processList = [(clipper_utm11,outws_utm11, ras) for ras in rasters]
clipRasterMulti(processList)
print "Processing complete."
if __name__ == '__main__':
main()