1

I wrote my code in Jupyter notebook and it works through the Jupyter environment and as well as on Python terminal inside of the ArcGIS Pro. I am trying to convert it into a toolbox to use it for different purposes, I followed the guide to create a toolbox but I cannot make it work and I get error when using Calculate Field and try to access a column that was created by Join. Here is the code, ignore the variables I do not use.

# -*- coding: utf-8 -*-

import arcpy

class Toolbox(object):
    def __init__(self):
        """Define the toolbox (the name of the toolbox is the name of the
        .pyt file)."""
        self.label = "Toolbox"
        self.alias = "nearToolBox"

        # List of tool classes associated with this toolbox
        self.tools = [Tool]

class Tool(object):
    def __init__(self):
        """Define the tool (tool name is the name of the class)."""
        self.label = "Tool"
        self.description = ""
        self.canRunInBackground = False

    def getParameterInfo(self):
        """Define parameter definitions"""
        params = None
        return params

    def isLicensed(self):
        """Set whether tool is licensed to execute."""
        return True

    def updateParameters(self, parameters):
        """Modify the values and properties of parameters before internal
        validation is performed.  This method is called whenever a parameter
        has been changed."""
        return

    def updateMessages(self, parameters):
        """Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation."""
        return

    def execute(self, parameters, messages):
        """The source code of the tool."""
        import arcpy
        import os

        arcpy.env.workspace = r"C:\Users\USER\Desktop\NearProjesi\Near.gdb"
        arcpy.env.overwriteOutput = True
        in_features = "Bina"
        near_features = "Yol"

        out_table = "bina_yol_yakinlik"
        search_radius = '1500 Meters'
        location = 'NO_LOCATION'
        angle = 'NO_ANGLE'
        closest = 'ALL'
        closest_count = 3
        arcpy.CopyFeatures_management("Bina", "bina_kopya")
        # arcpy.CopyFeatures_management("Yol", "yol_kopya")
        arcpy.GenerateNearTable_analysis("bina_kopya", "Yol", out_table, search_radius, location, angle, closest,
                                         closest_count)
        arcpy.AddJoin_management(out_table, 'NEAR_FID', 'Yol', "OBJECTID", "KEEP_COMMON")
        arcpy.management.CalculateField(out_table, "YOL_ADI", "!Yol.yoladi!", "PYTHON3")
        arcpy.management.RemoveJoin(out_table)

        in_fc = r"C:\Users\USER\Desktop\NearProjesi\Default.gdb\bina_yol_yakinlik"
        nearest_dict = dict()

        with arcpy.da.SearchCursor(in_fc, ["YOL_ADI", "IN_FID"]) as rows:
            for row in rows:
                nearest_id = row[0]  # get OID value for that row
                input_id = row[1]  # get NEAR_FID value

                if input_id in nearest_dict:
                    # if a dict key already exists, append near id to value list for that key
                    nearest_dict[input_id].append(nearest_id)
                else:
                    # if the key does not exist then create a new list with near id
                    # and add it to the dictionary
                    nearest_dict[input_id] = [nearest_id]

        return

the error is

Traceback (most recent call last):
  File "<string>", line 61, in execute
  File "C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\management.py", line 5209, in CalculateField
    raise e
  File "C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\management.py", line 5206, in CalculateField
    retval = convertArcObjectToPythonObject(gp.CalculateField_management(*gp_fixargs((in_table, field, expression, expression_type, code_block, field_type), True)))
  File "C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\geoprocessing\_base.py", line 511, in <lambda>
    return lambda *args: val(*gp_fixargs(args, True))
arcgisscripting.ExecuteError:  ERROR 000539: Invalid field yol.yoladi
Failed to execute (CalculateField).
 Failed to execute (Tool).

link

If you could look at this, the first output is the one generated by the very first join: arcpy.AddJoin_management(out_table, 'NEAR_FID', 'Yol', "OBJECTID", "KEEP_COMMON")

the second one is: arcpy.management.CalculateField(out_table, "YOL_ADI", "!yol.yoladi!","PYTHON3", "TEXT")

and the third one is after i do: arcpy.management.RemoveJoin(out_table)

I am able to do this on jupyter notebook and as well as python terminal. But when i put it in the toolbox and run in i get the error on the second code i shared which is this one again :

arcpy.management.CalculateField(out_table, "YOL_ADI", "!yol.yoladi!","PYTHON3")

In this part i am trying to make a new column named as "YOL_ADI" and copy the data from the Yol->yoladi which i have on the output table. I tried to set field type parameter but it did not help. @Hornbydd

3
  • Generally the idea behind a toolbox is to accept runtime parameters from the UI. Hard-codng all the variables defeats the purpose, incurring framework constraints without any function benefit.
    – Vince
    Jun 10 at 12:12
  • Yeah, i agree with that part. But i am planning on adding userinput in the future. Now my aim is to make a toolbox that can work and parameter inputting will come later. @Vince
    – Fatih Enes
    Jun 10 at 12:17
  • 1
    Sure, here is the link to sample code and as well as dataset (i am uploading the project) You need to change the path. link @Hornbydd
    – Fatih Enes
    Jun 10 at 13:39
1

Having reviewed your code with your sample data to help and checked the help file I worked out the problem to be was how you were referencing the table. The Add Join tool requires as input a Table View, this is stated in the help file under the syntax section. You were not providing a table VIEW you were providing a full path to a table. This was obviously messing with the calculate field tool. I have rewritten your code below, replace it and it will work.

Below is the updated execute code()

def execute(self, parameters, messages):
        """The source code of the tool."""
        import arcpy
        import os

        arcpy.env.workspace = r"C:\Users\USER\Desktop\NearProjesi\Near.gdb"
        arcpy.env.overwriteOutput = True
        in_features = "Bina"
        near_features = "Yol"

        out_table = "bina_yol_yakinlik"
        search_radius = '1500 Meters'
        location = 'NO_LOCATION'
        angle = 'NO_ANGLE'
        closest = 'ALL'
        closest_count = 3
        arcpy.CopyFeatures_management("Bina", "bina_kopya")
        arcpy.GenerateNearTable_analysis("bina_kopya", "Yol", out_table, search_radius, location, angle, closest, closest_count)
        arcpy.AddField_management(out_table, "YOL_ADI", "TEXT")
        arcpy.MakeTableView_management(out_table,"tempTableView")
        arcpy.AddJoin_management("tempTableView", 'NEAR_FID', 'Yol', "OBJECTID", "KEEP_ALL")
        arcpy.management.CalculateField("tempTableView", "YOL_ADI", "!Yol.yoladi!", "PYTHON3")
        arcpy.management.RemoveJoin("tempTableView")

        nearest_dict = dict()

        with arcpy.da.SearchCursor("tempTableView", ["YOL_ADI", "IN_FID"]) as rows:
            for row in rows:
                nearest_id = row[0]  # get OID value for that row
                input_id = row[1]  # get NEAR_FID value

                if input_id in nearest_dict:
                    # if a dict key already exists, append near id to value list for that key
                    nearest_dict[input_id].append(nearest_id)
                else:
                    # if the key does not exist then create a new list with near id
                    # and add it to the dictionary
                    nearest_dict[input_id] = [nearest_id]
        arcpy.AddMessage(nearest_dict)
        
        return

I assume how these tools are implemented in the jupyter notebook must be different to the python toolbox environment.

3
  • Thank you! It works and i can see the output because you hava added it as well. I am fairly new to creating stuff in this field so your help meant a lot to me. @Hornbydd
    – Fatih Enes
    Jun 10 at 16:04
  • I was wondering one more thing before if it can be created through the toolbox,. So as you know i have a dictionary and it has keys and values, the keys are points and values are roads that are closest to that specific point, i want to be able to create a drop down menu and let the user see the three closest road and pick one from it and write it back to the data file (by picking it, asking user to enter something). Is this idea possible through a toolbox? Thanks a lot again. @Hornbydd
    – Fatih Enes
    Jun 10 at 16:12
  • That type of logic would have to run in the updateParameters() but my gut feeling is that is not appropriate. Parameters are typically something you select or set. You would not put spatial selection logic into a parameter for performance reasons.
    – Hornbydd
    Jun 10 at 18:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.