1

我有关于乘法嵌套语句的一般问题。对于“复杂嵌套”(> 3/4层),什么是更好的方法,尤其是迭代AND使用if语句时更是如此?for循环中嵌套的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: 

,然后我真正进入码处理的肉。坦率地说,我想不出一种方法来避免这些嵌套的条件语句和循环语句。有什么我失踪?我应该使用“while”而不是“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个小时以上。建立在我原来的问题上,这可能是因为它是如此深嵌套?或者情况并非如此,数据只需要时间来处理?

+2

你为什么不把它分解成函数? –

+0

我很抱歉你在这里指出,也许你应该已经[重定向到代码评论](http://meta.stackoverflow.com/questions/253975/be-careful-when-recommending-code-review-to因为你在原始文章中有完整的工作代码。 – iled

+1

对于我来说,看起来并不值得麻烦,因为考虑到这个任务有多大,我会试着将它分解为并行处理。 –

回答

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") 

通常你会加入池的结果,但由于您使用此执行任务的我不知道这是必要的。其他人可能会对最佳做法有所了解。

+0

感谢@Nate Wanner关于如何开始多进程的提示。那么你的观点是,代码本身对于任务来说不一定是“低效的”,但是修改它以适应多包装或将任务分解为多次运行就是答案 – Kevin

+0

@Kevin我的意图是给你一个多处理的起点。你的脚本对我来说听起来很慢,但是我不确定你有什么大小的数据集,或者它们是如何存储和访问的。我怀疑你可能会使用一种工具,一次只能复制一个功能,当你可能使用一个工具来复制gdb表格时,但这只是我的假设,而我没有花时间来刷掉ArcPy。如果你还没有,Paul Zandbergen关于ArcShop Python脚本的书很好。 –

+0

@Kevin一对未经考验的想法:假定你正在合并的数据库是相同的模式,但对于不同的领域,你能避免使用fieldmapping吗?看起来这可能会减慢Append功能。如果空间参考更改,您也可能会遇到很大的性能提升。在脚本中,您可能更好地合并为一个空间参考,然后更改要素类的大小,而不是在Append内重新投影。 –