Hello,
I've got a python script that works as expected in the PyCharm IDE but when I try to run it as a tool in #ArcCatalog 10.5 it gets about 80% done and then fails. ArcCatalog simply closes without an error message. The script attempts to create polylines between pairs of features in two point layers that are linked by a common ID field. The data I'm using are address points (1st point layer) and their geocoded locations (2nd point layer).
I've noticed that the script fails in ArcCatalog precisely when it reaches the address points in the first layer that have no matching geocoded locations in the second layer. Yet because the script works in PyCharm without issue and no error message is generated by ArcCatalog I am not sure why it fails.
Any wisdom on this problem would be greatly appreciated. Thanx!
P.S. I've attached my script for reference.
If it is a script in a toolbox, then add the toolbox to arctoolbox and run it from there. I have seen cases where tools in user toolboxes fail in Catalog but work in ArcToolbox.
As for the script, you have nested try-except blocks and 2 searchcursors. I would break up your workflow and put the pieces in functions (aka a def), gather the bits to assemble the shape and make sure that works. nested try-except blocks aren't recommended. In fact, I have totally given up on them since it is just as easy to trap errors before they occur in code and get a meaningful message before things fail.
Thanx, Dan. I actually am using the ArcToolbox in ArcCatalog. Sorry that wasn't made clear.
I will fix the script as you suggest and try it again. I wondered if my rusty coding skills hadn't produced a memory or CPU-eating monster that was causing the problem for ArcGIS.
Jim re-share if you get changes made.
As for running scripts in ArcToolbox... yes, just run arctoolbox from within ArcMap and not ArcCatalog... As I was alluding to, I have seen issues when toolbox is from there that aren't present within arcmap
Looking at the code, I would do a number of things differently. Some pointers below:
BTW, I did not test the code, so there are likely errors in it. If you want, post some data and I will test to see if it works,
def main():
import arcpy
import os
try:
# Example parameters:
# - "C:\Work\NG-911\Data\Data_Readiness\Central\swift\GIS\adp\SwiftAddressPoints_20180110.shp"
# - "JIMS_ID"
# - "C:\Work\NG-911\Data\Data_Readiness\Central\swift\GIS\geocoder\swift_adp_to_rcl_geocodes.shp"
# - "JIMS_ID"
# - "C:\temp\SwiftAddressPoints_fishbone.shp"
from_pts = arcpy.GetParameterAsText(0) # Shapefile/Feature Class with starting points for lines
from_fld = arcpy.GetParameterAsText(1) # Field in starting points table that links it to ending points table
to_pts = arcpy.GetParameterAsText(2) # Shapefile/Feature Class with ending points for lines
to_fld = arcpy.GetParameterAsText(3) # Field in ending points table that links it to starting points table
out_file = arcpy.GetParameterAsText(4) # Output Shapefile/Feature Class path containing lines
fld_id = "Link_ID"
# create dictionaries of from and to fc's
dct_from = {r[0]: r[1] for r in arcpy.da.SearchCursor(from_pts, (from_fld, 'SHAPE@'))}
dct_to = {r[0]: r[1] for r in arcpy.da.SearchCursor(to_pts, (to_fld, 'SHAPE@'))}
# you could (should?) also check if all from and to points have a matching point
from_ids = set(dct_from.keys())
to_ids = set(dct_to.keys())
from_dangles = list(from_ids - to_ids)
to_dangles = list(to_ids - from_ids)
if len(from_dangles) > 0:
arcpy.AddWarning("From dangels:\n:{}".format(from_dangles))
if len(to_dangles) > 0:
arcpy.AddWarning("To dangels:\n:{}".format(to_dangles))
# check if there are any matching from and to ids
line_ids = list(from_ids & to_ids)
if len(line_ids) > 0:
# create output featureclass
ws, fc_name = os.path.split(out_file)
spatialRef = arcpy.Describe(from_pts).spatialReference # Get spatial reference of starting points Shapefile/Feature Class
arcpy.CreateFeatureclass_management(ws, fc_name, "POLYLINE", None, None, None, spatialRef)
# add id field to output
fld_from_id = arcpy.ListFields(from_pts, from_fld)
AddField(out_file, fld_id, fld_from_id)
# start insert cursor
with arcpy.da.InsertCursor(out_file, (fld_id, 'SHAPE@')) as curs:
for link_id in line_ids:
try:
pntg1 = dct_from[link_id]
pntg2 = dct_to[link_id]
polyline = arcpy.Polyline(arcpy.Array([pntg1.firstPoint, pntg2.firstPoint]), spatialRef)
curs.insertRow((link_id, polyline, ))
except Exception, err:
print err.message, link_id
# Persist a copy of the Polyline objects using CopyFeatures
arcpy.AddGeometryAttributes_management(out_file, "LENGTH") # Add Length geometry field to out_file
except Exception, err:
print err.message # gp.AddError(err.message)
def AddField(fc, fld_name, fld_templeate):
arcpy.AddField_management(fc, fld_name, fld.type, fld.precision, fld.scale, fld.length)
if __name__ == '__main__':
main()