ArcPy – How to Trace a Geometric Network in a Custom Script Tool for ArcGIS 10.3

arcgis-10.3arcpygeometric-networkpython-script-tool

I'm trying to make a Python script tool which uses the Trace Geometric Network tool (10.3). My script works in the Python window, but as a script-tool, it runs and NOTHING HAPPENS. Messages state: Executing…, Start time…, Running script…, Completed script… Succeeded at… It acts like the tool executed with no errors, but there's no visible output.

The Trace Geometric Network tool refuses to work inside a Python script tool the way it does in the Python window. I tried playing with the parameters, data types in of parameter settings, and deleting and remaking the tool several times. I even tried using other geometric networks with the tool. Finally, I made a bare-bones script with only the trace tool to troubleshoot, and NOTHING. I get the same action as above.

Here's my bare-bones script:

geoNetwork = arcpy.GetParameterAsText(0)

inflags = arcpy.GetParameterAsText(1)

barriers = arcpy.GetParameterAsText(2)

arcpy.TraceGeometricNetwork_management(geoNetwork, "Trace", inflags, "TRACE_DOWNSTREAM", barriers)

Here's a screen shot of how I'm setting my parameters in the tool properties:

Tool Parameter Properties

How can I to get this to work as a Python script tool?

Here's the actual code. As this tool executes, I can see it looping over the flags and selecting them one by one. No output group layer files are added to the map and no apparent traces are made. Again, these functions work as intended if pasted in the python window, but misbehave as python-script tools.

inflags = arcpy.GetParameterAsText(0)
geoNetwork = arcpy.GetParameterAsText(1)
barriers = arcpy.GetParameterAsText(2)
outPath = arcpy.GetParameterAsText(3)
outName = arcpy.GetParameterAsText(4)

def makeFullPath(path, name):
    return path + "\\" + name

def TraceCapture(inflags, geoNetwork, barriers, outPath, outName):  
    mxd = arcpy.mapping.MapDocument("CURRENT")
    df = arcpy.mapping.ListDataFrames(mxd)[0]
    flagList = list(arcpy.da.SearchCursor(inflags, 'UNITID'))
    trace = 1
    segmentCapture = []
    for flag in range(1, len(flagList)+1): 
        try:
            outputLayer = "Trace_" + str(trace)
            expression = '"OBJECTID" =' + str(trace)
            arcpy.SelectLayerByAttribute_management(inflags, "NEW_SELECTION", expression)
            arcpy.TraceGeometricNetwork_management(geoNetwork, outputLayer, inflags, "TRACE_DOWNSTREAM", barriers)
            arcpy.AddMessage("Trace_" + str(trace) + " complete")

            for lyr in arcpy.mapping.ListLayers(mxd, "", df):
                if lyr.name == "Sewers":
                    pipesCursor = arcpy.da.SearchCursor(lyr, 'ASSETID')
                    for i in pipesCursor:
                        segmentCapture.append((flagList[trace - 1][0], i[0]))
                if lyr.name == outputLayer:
                    arcpy.mapping.RemoveLayer(df, lyr)
            trace += 1
        except RuntimeError:
            print "Flag " + str(trace) + " was invalid and skipped."
            trace += 1
            continue

    arcpy.CreateTable_management(outPath, outName)
    outFile = makeFullPath(outPath, outName)
    arcpy.AddField_management(outFile, "manholeID", "TEXT", "", "", 10)
    arcpy.AddField_management(outFile, "pipeID", "TEXT", "", "", 10)

    with arcpy.da.InsertCursor(outFile, ["manholeID", "pipeID"]) as cursor:
        for row in segmentCapture:
            cursor.insertRow(row)

TraceCapture(inflags, geoNetowrk, barriers, outPath, outName)

Best Answer

Odds are it has finished, and finished properly. You don't have any outputs on your tool, thus the script tool wont return anything to your ArcMap session.

In most Trace models/scripts I've seen, you need to Select Data to pull out whatever child element you want, then its good to run Copy Features on that item. The output of CopyFeatures should be passed into one more variable you need to define on the Parameters page you've shown. You can set it as a derived output if you're handling the output location of the data in your script.

Model

See the picture of the model here where you can see Select and Make Feature Layer after the Trace tool (but dont use Make Feature Layer, use Copy Features). Note that the Select tool is a ModelBuilder ONLY tool. The workflow is different in Python.

Python

To select an item out of the group layer, you need to have prior knowledge of what it's name will be. The below code shows you can list the sub items of a group layer to get their name. Having prior knowledge of the names, you just need to build up a path to the output using traceName/subLayerName. (arcpy.mapping code is only added for reference to print out all available item names, in practice you probably wouldn't add this to a production tool)

arcpy.Snap_edit(Flags, "'Primary OH Conductor' VERTEX '30 Meters'")

arcpy.TraceGeometricNetwork_management(El_Paso_Electric, "Storm_Net", Flags, "TRACE_UPSTREAM", "", "", "", "", "", "NO_TRACE_ENDS", "TRACE_INDETERMINATE_FLOW", "", "", "AS_IS", "", "", "", "AS_IS")

network = arcpy.mapping.Layer("Storm_Net")
if network.isGroupLayer:
    for sublayer in network:
        arcpy.AddMessage("  {} ".format(sublayer.name))

# Process: Select Data
#arcpy.SelectData_management("Storm_Net", "ServiceLocation")  # <--- dont use

# Build up the path to the item you want, in this case, "Storm_Net" is my output Trace, and "ServiceLocation" is the item inside I want.
arcpy.CopyFeatures_management("Storm_Net/ServiceLocation", outputFeatureClass)
Related Question