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內重新投影。 –