Working with Python Functions/Methods and ArcPy

4803
8
10-24-2016 09:41 AM
GeoffreyWest
Occasional Contributor III

I have this block of code that I would like repeated 21 times.  It creates a feature layer, executes summary statistics, joins a field, executes update cursor twice, for a line and polygon feature class.  Lastly, it calculates a field and deletes two fields.

Can somebody please explain to me the logic of the Python method/function?  How does the program know which variable should be called within an ArcPy function?  

The block of code below has within the first function what I would like executed 21 times.  However, when the SummaryStats(DistrictConfig) is executed, I do not receive my expected output.  What is being done incorrectly?  

import arcpy
import DistrictConfig
import logging
import logging.handlers
import ConfigParser
LOGGER_NAME = 'korterra_district'
arcpy.env.workspace = r"C:\KorTerraTables\tables_db.gdb"
arcpy.env.overwriteOutput = True
from datetime import datetime
startTime = datetime.now()
logger = logging.getLogger(LOGGER_NAME)
distfc = DistrictConfig.distfc
linefc = DistrictConfig.linefc
polyfc = DistrictConfig.polyfc
totalexpression = DistrictConfig.TotalExpression
totalscline = DistrictConfig.TotalSCLine
totalscpoly = DistrictConfig.TotalSCPoly
statsfield = DistrictConfig.StatsField
fields = DistrictConfig.fields
totalCalc = DistrictConfig.TotalCalc
unique_name = arcpy.CreateUniqueName("featureLyr")
transPoly = DistrictConfig.Overdue_Expression_SC_Tran
overDueLine = DistrictConfig.OverdueTableSC_TransLine
overDueExpression = DistrictConfig.Overdue_Expression
statusCaseFields = DistrictConfig.CaseFields
TotalLong ="TOTAL_LONG"
OverDueTotal = "OVERDUE"



def DistrictFunction(DistrictConfig, distfc, totalexpression, totalscline, statsfield, fields,TotalLong):
 print "Calculating Total Line Tickets per District"
 arcpy.MakeFeatureLayer_management(linefc, unique_name, totalexpression)
 arcpy.Statistics_analysis(unique_name, totalscline , statsfield, "DISTRICT")
 arcpy.JoinField_management(distfc, "NAME", totalscline, "DISTRICT", fields)
with arcpy.da.UpdateCursor(distfc, ["FREQUENCY"]) as cursor:
 for row in cursor:
 if row[0] == None:
 row[0] = 0
 cursor.updateRow(row)
#Calculate and Join Totals per District Polys
 arcpy.MakeFeatureLayer_management(polyfc, unique_name, totalexpression)
 arcpy.Statistics_analysis(unique_name, totalscpoly , statsfield, "DISTRICT")
 arcpy.JoinField_management(distfc, "NAME", totalscpoly, "DISTRICT", fields)
with arcpy.da.UpdateCursor(distfc, ["FREQUENCY_1"]) as cursor:
 for row in cursor:
 if row[0] == None:
 row[0] = 0
 cursor.updateRow(row)
arcpy.CalculateField_management(distfc, TotalLong, totalCalc)
 arcpy.DeleteField_management(distfc, ["FREQUENCY", "FREQUENCY_1"])

def SummaryStats(DistrictConfig):
 try:
## DistrictFunction(DistrictConfig, distfc, totalexpression, totalscline, statsfield, fields, TotalLong )
## DistrictFunction(DistrictConfig, distfc, totalexpression, totalscpoly, statsfield, fields, TotalLong)
 DistrictFunction(DistrictConfig, distfc, overDueExpression, overDueLine, statsfield, fields, OverDueTotal)
 except Exception as e:
 logger.info(e.message, exc_info=True)
 raise e








0 Kudos
8 Replies
KristenE
New Contributor III

Functions use variables to define parameters (stuff inside the parenthesis that can change each time you call the function). In the above code you are defining your functions, but you are not executing them.

# Define function
def do_something(variable1, variable2):
    # do something with variable1
    # do something with variable2

# Call the function
do_something(x, y)

# Call the function again using different values
do_something(a, b)

The first time I called the function ‘x’ was plugged in for variable1 and ‘y’ was plugged in for variable2. The second time I called the function ‘a’ was plugged in for variable1 and ‘b’ was plugged in for variable2.

GeoffreyWest
Occasional Contributor III

So Kristen,

When you say that I am not executing the functions, how should my code be

modified so that I can execute the 3rd call of DistrictFunction in my

SummaryStats function?

0 Kudos
KristenE
New Contributor III

Are you missing some code in the above block? Is there a line later in the code where you call SummaryStats? In order to execute the code you would have to call SummaryStats like so:

SummaryStats(DistrictConfig)

I'm not sure I understand why you have 2 functions. It looks like the second one just calls the first one. And your comments are different ways you would like to run it? I would just have one function and call it 3 times (or 21 times).

# Define the funtion
def DistrictFunction(DistrictConfig, distfc, totalexpression, totalscline, statsfield, fields,TotalLong):
    print "Calculating Total Line Tickets per District"
    arcpy.MakeFeatureLayer_management(linefc, unique_name, totalexpression)
    arcpy.Statistics_analysis(unique_name, totalscline , statsfield, "DISTRICT")
    arcpy.JoinField_management(distfc, "NAME", totalscline, "DISTRICT", fields)
    with arcpy.da.UpdateCursor(distfc, ["FREQUENCY"]) as cursor:
        for row in cursor:
            if row[0] == None:
                row[0] = 0
            cursor.updateRow(row)
    #Calculate and Join Totals per District Polys
    arcpy.MakeFeatureLayer_management(polyfc, unique_name, totalexpression)
    arcpy.Statistics_analysis(unique_name, totalscpoly , statsfield, "DISTRICT")
    arcpy.JoinField_management(distfc, "NAME", totalscpoly, "DISTRICT", fields)
    with arcpy.da.UpdateCursor(distfc, ["FREQUENCY_1"]) as cursor:
        for row in cursor:
            if row[0] == None:
                row[0] = 0
                cursor.updateRow(row)
    arcpy.CalculateField_management(distfc, TotalLong, totalCalc)
    arcpy.DeleteField_management(distfc, ["FREQUENCY", "FREQUENCY_1"])

# Call the function 3 times
try:
    DistrictFunction(DistrictConfig, distfc, totalexpression, totalscline, statsfield, fields, TotalLong)
    DistrictFunction(DistrictConfig, distfc, totalexpression, totalscpoly, statsfield, fields, TotalLong)
    DistrictFunction(DistrictConfig, distfc, overDueExpression, overDueLine, statsfield, fields, OverDueTotal)
except Exception as e:
    logger.info(e.message, exc_info=True)
    raise e‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
JamesCrandall
MVP Frequent Contributor

The block of code below has within the first function what I would like executed 21 times

Then you would just iterate over 21 times:

def DistrictFunction(DistrictConfig, distfc, totalexpression, totalscline, statsfield, fields,TotalLong):
    for i in range(21):
       print "Calculating Total Line Tickets per District"
       arcpy.MakeFeatureLayer_management(linefc, unique_name, totalexpression)
       arcpy.Statistics_analysis(unique_name, totalscline , statsfield, "DISTRICT")
       .
       .
       .
       .
0 Kudos
GeoffreyWest
Occasional Contributor III

James,

I should have specified 21 times with different parameters each time.   

0 Kudos
JamesCrandall
MVP Frequent Contributor

I should have specified 21 times with different parameters each time

You want the impossible unless you can explain the specifics of each parameter.  I suspect your DistrictConfig contains everything but we are not going to be able to help without knowing what's in it.

distfc = DistrictConfig.distfc

I'm not exactly sure what this even is because you are importing it from another python class.

0 Kudos
MicahBabinski
Occasional Contributor III

Hey Geoffrey,

I would add that your DistrictFunction function collects DistrictConfig as an input parameter but doesn't actually use it anywhere in the function.

If you need the functions run 21 one times with 21 different sets of parameters, you may with to store those parameters in a table. Each row would contain all the values required by your function. Then, read that table with an arcpy data access search cursor and run your function each time.

Something along the lines of:

def DistrictFunction(distfc, totalexpression, totalscline, statsfield, fields, TotalLong):
    # your logic

# create variables for your parameter table and the fields in that table you will interact with
paramterTable = r"[Path to Parameter Table]"
fields = ("distfc", "totalexpression", "totalscline", "statsfield", "fields", "TotalLong")

# read the paramter table with a search cursor and run your function
with arcpy.da.SearchCursor(table, fields) as cursor:
    for row in cursor:
        DistrictFunction(row[0], row[1], row[2], row[3], row[4], row[5])‍‍‍‍‍‍‍‍‍‍‍

Good luck.

Micah

0 Kudos
GeoffreyWest
Occasional Contributor III

I was able to sort this out; I mistakingly had used a variable

incorrectly. Here is my corrected code.

  1. Define the funtion

def DistrictFunction(distfc, totalexpression, totalscline, statsfield,

fields,TotalLong):

print "DistrictFunction called"

print "distfc: " + distfc

print "totalexpression: " + totalexpression

print "totalscline: " + totalscline

print statsfield

print fields

print TotalLong

unique_name = arcpy.CreateUniqueName("featureLyr")

arcpy.MakeFeatureLayer_management(linefc, unique_name, totalexpression)

arcpy.Statistics_analysis(unique_name, totalscline , statsfield,

"DISTRICT")

arcpy.JoinField_management(distfc, "NAME", totalscline, "DISTRICT",

fields)

with arcpy.da.UpdateCursor(distfc, ["FREQUENCY"]) as cursor:

for row in cursor:

if row[0] == None:

row[0] = 0

cursor.updateRow(row)

#Calculate and Join Totals per District Polys

arcpy.MakeFeatureLayer_management(polyfc, unique_name, totalexpression)

arcpy.Statistics_analysis(unique_name, totalscpoly , statsfield,

"DISTRICT")

arcpy.JoinField_management(distfc, "NAME", totalscpoly, "DISTRICT",

fields)

with arcpy.da.UpdateCursor(distfc, ["FREQUENCY_1"]) as cursor:

for row in cursor:

if row[0] == None:

row[0] = 0

cursor.updateRow(row)

arcpy.CalculateField_management(distfc, TotalLong, totalCalc)

arcpy.DeleteField_management(distfc, ["FREQUENCY", "FREQUENCY_1"])

def SummaryStats():

try:

DistrictFunction(distfc, totalexpression, totalscline, statsfield,

fields, TotalLong)

DistrictFunction(distfc, totalexpression, totalscpoly, statsfield,

fields, TotalLong)

DistrictFunction(distfc, overDueExpression, overDueLine,

statsfield, fields, OverDueTotal)

DistrictFunction(distfc, overDueExpression, OverDuePoly,

statsfield, fields, OverDueTotal)

DistrictFunction(distfc, inProgressExpression, inProgressLine,

statsfield, fields, inProgresstotal)

DistrictFunction(distfc, inProgressExpression, inProgressPoly,

statsfield, fields, inProgresstotal)

DistrictFunction(distfc, unKnownExpression, unKnownLine,

statsfield, fields, unKnownTotal)

DistrictFunction(distfc, unKnownExpression, unKnownPoly,

statsfield, fields, unKnownTotal)

DistrictFunction(distfc, upComingExpression, upComingLine,

statsfield, fields, upComingTotal)

DistrictFunction(distfc, upComingExpression, upComingPoly,

statsfield, fields, upComingTotal)

except Exception as e:

logger.info(e.message, exc_info=True)

raise e

SummaryStats()