0

I'm trying to get my script in multiprocessing, but the arcpy.management.CalculateGeometryAttributes produced None values. I tried it in for loop and it worked perfectly fine.

import os
import datetime
import arcpy 
import multiprocessing
import sys

def process(fc):
        arcpy.env.workspace = "G:/usgrids2020/test1/"
        arcpy.env.overwriteOutput=True
        state = fc[34:-7]
        print(f"Processing for {state.upper()}")
        readTime = datetime.datetime.now()
        # arcpy.env.workspace = os.path.join(gdb_path, f"usa{state}.gdb")
        #Import the feature for boundary and water
        # fc = f"usa{state[3:5]}_joined"
        fcInMem = arcpy.management.CopyFeatures(fc, f"in_memory/usa{state}_fcInMem")
        water_fc = f"{fc[:-7]}_water_layer"
        waterInMem = arcpy.management.CopyFeatures(water_fc, f"in_memory/usa{state}_waterInMem")
        #Create the temporary id for joining fields later
        arcpy.AddField_management(fcInMem,'tempid','LONG')
        arcpy.CalculateField_management(fcInMem,"tempid",'!OBJECTID!','PYTHON')
        #Calculate the area(land+water) by GEODESIC method => Kytt recommended
        arcpy.management.AddField(fcInMem, "GEODESIC_AREA", "FLOAT")
        arcpy.management.CalculateGeometryAttributes(fcInMem, "GEODESIC_AREA AREA_GEODESIC", "", "SQUARE_METERS")        
        print("Starting intersect fishnet to boundary...")
        fish_net = f"G:/usgrids2020/fishnets/usa{state}_fishnet.gdb/usa{state}_fishnet"
        fishnetInMem = arcpy.management.CopyFeatures(fish_net, f"in_memory/{state}_fishnetInMem")
        intersectOut = f"in_memory/{state}intersect_fc"


    with arcpy.da.SearchCursor(fcInMem, ["GEODESIC_AREA", "GEOID20"]) as cursor:
        for i in range(10):
            for row in cursor:
                print(row)
                break
    print("Summarizing...")
    print(f"Finished processing for {state.upper()} in {str(datetime.datetime.now() - readTime)}")




def main():
    arcpy.env.workspace = "G:/usgrids2020/test1/"
    gdbs = arcpy.ListWorkspaces("*", "FILEGDB")
    procList = [os.path.join(gdb,f"{os.path.basename(gdb)[:-4]}_joined") for gdb in gdbs]
    multiprocessing.set_executable(os.path.join(get_install_path(), 'python.exe'))
    pool = multiprocessing.Pool(processes=2,maxtasksperchild=1)
    results = pool.map(process, procList)
    
    for result in results:
        print(result)

    # Synchronize the main process with the job processes to
    # ensure proper cleanup.
    pool.close()
    pool.join()

def get_install_path():
    ''' Return 64bit python install path from registry (if installed and registered),
        otherwise fall back to current 32bit process install path.

        Copied from https://gis.stackexchange.com/a/140777/2856
    '''
    if sys.maxsize > 2**32: return sys.exec_prefix #We're running in a 64bit process

    #We're 32 bit so see if there's a 64bit install
    path = r'SOFTWARE\Python\PythonCore\2.7'

    from winreg import OpenKey, QueryValue
    from winreg import HKEY_LOCAL_MACHINE, KEY_READ, KEY_WOW64_64KEY

    try:
        with OpenKey(HKEY_LOCAL_MACHINE, path, 0, KEY_READ | KEY_WOW64_64KEY) as key:
            return QueryValue(key, "InstallPath").strip(os.sep) #We have a 64bit install, so return that.
    except: return sys.exec_prefix #No 64bit, so return 32bit path

if __name__ == '__main__':
    main()

The sample above produced this

(None, 'USA_100030117003015')
(None, 'USA_100030127001011')
(None, 'USA_100030151002006')
(None, 'USA_100030121001003')
(None, 'USA_100030112051009')
(None, 'USA_100030148102015')
(None, 'USA_100030112062022')
(None, 'USA_100030168063009')
(None, 'USA_100030166141010')
(None, 'USA_100030164041013')

And the expected output should be

(20561.794921875, 'USA_110010105004003')
(30113.7734375, 'USA_110010079014005')
(12254.59765625, 'USA_110010022022000')
(35741.94921875, 'USA_110010105004002')
(4266.21240234375, 'USA_110010070002021')
(3911.968994140625, 'USA_110010055021003')
(4928.87890625, 'USA_110010031001004')
(17638.513671875, 'USA_110010104002006')
(120078.6015625, 'USA_110010009042003')
(47717.84375, 'USA_110010105003001')
(27098.328125, 'USA_110010105004008')
(14594.705078125, 'USA_110010032004000')
(34655.69140625, 'USA_110010025042001')
5
  • 1
    StackExchange content is is CC-BY-SA licensed. So when you copy code from here, you are required to attribute it - stackoverflow.com/help/licensing
    – user2856
    Commented Jun 18 at 13:42
  • I might be wrong but think the problem is that you are using a single location for each process to write to, the in_memory workspace. Try for each process writing to a separate unique dataset? Have a look at my code here.
    – Hornbydd
    Commented Jun 18 at 17:05
  • @Hornbydd it's confused because the other functions from arcpy worked fine such as AddField and CalculateField, but when it came to CalculateGeometryAttributes the function generated None values
    – Hieu Tran
    Commented Jun 18 at 17:27
  • 1
    Looks to be a defect with CalculateGeometryAttributes. I was able to create a minimum reproducible example and have submitted to Esri Support to log a defect. Will update when I know more.
    – bixb0012
    Commented Jun 18 at 19:10
  • Thanks for the updates. Hopefully it is a defect with the function.
    – Hieu Tran
    Commented Jun 18 at 23:17

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.