在for循环

时间:2017-02-21 23:02:25

标签: python if-statement nested-loops processing-efficiency coding-efficiency

我有关于多重嵌套语句的一般性问题。对于"复杂的嵌套" (> 3/4层),什么是更好的方法,特别是在迭代AND使用if语句时?

我有很多文件,其中一些在子目录中,另一些在根目录中。有许多目录,我想从中提取数据集并附加到目标数据集(主数据集)。

for special_directory in directorylist:
    for dataset in special_directory:
        if dataset in list_of_wanted:
        some_code
        if it_already_exists:
            for feature_class in dataset:
                if feature_class in list_of_wanted:

然后我真正深入了解代码处理的内容。坦率地说,我无法想出一种避免这些嵌套条件和循环语句的方法。有什么我想念的吗?我应该使用"而#34;而不是" for"?

我的实际具体代码有效。它只是不会很快移动。它迭代超过27个数据库,以将每个数据库的内容附加到新的目标数据库。我的python已经运行了36个小时,并且是4/27。提示?

我在GIS堆栈交换中发布了这个,但我的问题实在太过笼统,因为它不属于那里:question and more specific code

任何提示?这方面的最佳做法是什么?这已经是代码的一个子集。这样可以在其他脚本生成的列表的地理数据中查找其中的数据集和要素类。第三个脚本查找存储在地理数据库中的要素类(即不在数据集中)。

ds_wanted = ["Hydrography"]
fc_wanted = ["NHDArea","NHDFlowline","NHDLine","NHDWaterbody"]

for item in gdblist:
env.workspace = item
for dsC in arcpy.ListDatasets():
    if dsC in ds_wanted:
        secondFD = os.path.join(gdb,dsC)
        if arcpy.Exists(secondFD):
            print (secondFD + " exists, not copying".format(dsC))
            for fcC in arcpy.ListFeatureClasses(feature_dataset=dsC):
               if fcC in fc_wanted:
                   secondFC2 = os.path.join(gdb,dsC, fcC)
                   if arcpy.Exists(secondFC2):
                       targetd2 = os.path.join(gdb,dsC,fcC)
                   # Create FieldMappings object and load the target dataset
                   #
                       print("Now begin field mapping!")
                       print("from {} to {}").format(item, gdb)
                       print("The target is " + targetd2)
                       fieldmappings = arcpy.FieldMappings()
                       fieldmappings.addTable(targetd2)

                       # Loop through each field in the input dataset
                       #

                       inputfields = [field.name for field in arcpy.ListFields(fcC) if not field.required]
                       for inputfield in inputfields:
                       # Iterate through each FieldMap in the FieldMappings
                           for i in range(fieldmappings.fieldCount):
                               fieldmap = fieldmappings.getFieldMap(i)
                    # If the field name from the target dataset matches to a validated input field name
                               if fieldmap.getInputFieldName(0) == inputfield.replace(" ", "_"):
                        # Add the input field to the FieldMap and replace the old FieldMap with the new
                                   fieldmap.addInputField(fcC, inputfield)
                                   fieldmappings.replaceFieldMap(i, fieldmap)
                                   break
                   # Perform the Append
                   #
                       print("Appending stuff...")
                       arcpy.management.Append(fcC, targetd2, "NO_TEST", fieldmappings)
                   else:
                       arcpy.Copy_management(fcC, secondFC2)
                       print("Copied " +fcC+ "into " +gdb)
               else:
                   pass

        else:
            arcpy.Copy_management(dsC,secondFD) # Copies feature class from first gdb to second gdb
            print "Copied "+ dsC +" into " + gdb
    else:
        pass
        print "{} does not need to be copied to DGDB".format(dsC)

print("Done with datasets and the feature classes within them.")

似乎真的陷入了arcpy.management.Append 我对此功能有一些公平的经验,尽管这比典型的表模式(更多记录,更多字段)更大,但是单个附加需要12个多小时。基于我原来的问题,这可能是因为它是如此深层嵌套?或者情况并非如此,数据只需要时间来处理?

1 个答案:

答案 0 :(得分:0)

回答您的问题的一些好评。我在多处理方面的经验有限,但让所有计算机内核工作通常会加快速度。如果你有一个四核处理器,在脚本执行期间只运行25%左右,那么你可能会受益。你只需要小心如何应用它,以防一件事需要总是在另一件事之前发生。如果您正在使用文件地理数据库而不是企业gdb,那么您的瓶颈可能与磁盘有关。如果gdb是远程的,网络速度可能是问题。无论哪种方式,多处理都不会有帮助。 Windows上的资源监视器可以让您大致了解处理器/磁​​盘/ RAM /网络的使用量。

我刚刚使用了rpy2和来自/到PostGIS的数据的类似脚本。它仍然需要大约30个小时才能运行,但这比100好多了。我还没有在Arc中使用过多处理(我主要在开源工作),但知道有人。

多处理的一个非常简单的实现:

from multiprocessing import Pool

def multi_run_wrapper(gdblist):
    """Helper function to unpack argument lists during multiprocessing.
    Modified from: http://stackoverflow.com/a/21130146/4062147"""
    return gdb_append(*gdblist)  # the * unpacks the list

def gdb_append(gdb_id):
    ...

# script starts here #

gdblist = [......]

if __name__ == '__main__':
    p = Pool()
    p.map(multi_run_wrapper, gdblist)

print("Script Complete")

通常您会加入池的结果,但由于您使用它来执行任务,我不确定这是否必要。其他人可能会对什么是最佳实践感兴趣。