1

다중 중첩 구문과 관련된 일반적인 질문이 있습니다. "복잡한 네 스팅"(> 3/4 레이어)의 경우 특히 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: 

그리고 난 정말 코드 처리의 고기를 얻습니다. 솔직하게, 나는 이러한 중첩 된 조건문과 반복문을 피하는 방법을 생각할 수 없다. 제가 누락 된 것이 있습니까? "for"대신 "while"을 사용해야합니까?

내 특정 코드가 작동합니다. 그것은 아주 빨리 움직이지 않습니다. 27 개의 데이터베이스를 반복하여 각각의 내용을 새 대상 데이터베이스에 추가합니다. 내 파이썬은 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 에 하나의 APPEND를 잡힐 것 같다 12 시간 이상 걸립니다. 내 원래의 질문을 토대로하기 위해서, 이것이 깊이 중첩되어 있기 때문일 수 있습니까? 아니면 그렇지 않은가? 그리고 데이터는 단순히 처리하는 데 시간이 필요합니까?

+2

왜 함수로 분해하지 않습니까? –

+0

당신이 여기서 지적했음을 유감스럽게 생각합니다. 코드 검토로 리디렉션되어야합니다. (http://meta.stackoverflow.com/questions/253975/be-careful-when-recommending-code-review-to 원래 게시물에 전체 코드와 작업 코드가 있었기 때문에 처음부터. – iled

+1

나에게 귀찮은 가치는 보이지 않지만, 얼마나 큰 작업인지를 고려할 때, 병렬 처리를 위해 해체 할 생각입니다. –

답변

0

귀하의 질문에 대한 답변은 좋은 의견입니다. 멀티 프로세싱에 대한 경험은 제한적이지만 모든 컴퓨터 코어를 작동 시키면 속도가 빨라집니다. 스크립트 실행 중 약 25 % 만 실행되는 4 코어 프로세서를 사용하면 잠재적으로 이익을 얻을 수 있습니다. 한 가지가 항상 다른 상황보다 먼저 발생해야하는 경우에 대비하여주의 깊게 적용해야합니다. 엔터프라이즈 gdb가 아닌 파일 지오 데이터베이스로 작업하는 경우 병목 현상이 디스크와 관련 될 수 있습니다. gdb가 원격 인 경우 네트워크 속도가 문제 일 수 있습니다. 어느 쪽이든, 다중 처리는 도움이되지 않습니다. Windows의 리소스 모니터는 프로세서/디스크/RAM/네트워크의 사용량에 대한 일반적인 아이디어를 제공합니다.

방금 ​​전 rpy2와 PostGIS의 데이터를 사용하여 유사한 스크립트를 사용했습니다. 실행하는데 ~ 30 시간이 걸렸지 만, 이것은 100보다 훨씬 낫습니다. 아직 아크에서 멀티 프로세싱을 사용하지는 않았지만 (오픈 소스에서 주로 작업합니다), 가지고있는 사람들에 대해 알고 있습니다. 다중의

매우 간단한 구현 :

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 My Intent is just to 다중 처리에 대한 출발점을 제시하십시오. 스크립트가 나에게 느린 것처럼 들리지만 그렇다면 어떤 크기의 데이터 세트를 가지고 있는지, 어떻게 저장하고 액세스하는지에 대해서는 잘 모르겠습니다. 나는 gdb 테이블을 대량으로 복사하는 도구를 사용할 수있을 때 한 번에 하나씩 기능을 복사하는 도구를 사용하고 있을지도 모른다고 생각합니다. 그러나 그것은 내 부분에 대한 가설이며 ArcPy에서 브러시를 제거하지 않았습니다. Paul Zandbergen의 Arc에서의 Python 스크립팅에 대한 책은 아직 없으면 좋았습니다. –

+0

@Kevin 몇 안되는 생각 : 병합중인 데이터베이스가 동일한 스키마이지만 다른 영역에 있다고 가정하면 필드 매핑을 피할 수 있습니까? 잠재적으로 Append 기능을 느리게 할 수있는 것 같습니다. 공간 참조가 변경되면 성능이 크게 저하 될 수도 있습니다. 이 스크립트에서 하나의 공간 참조로 병합 한 다음 Append에서 재 투영하지 않고 대량의 피쳐 클래스를 변경하는 것이 더 나을 수 있습니다. –

관련 문제