I have a code in the following form. The problem i have is that some shapefiles don't have the specific fields DISTANCE, DURATION, so i tried to write a code with ListFields so as not to exit the commands but to go to the next shapefile. Unfortunately when the script finds a shp with fields which don't have DISTANCE DURATION, it terminates the procedure. Any help would be welcome. This code is in a try except
This is the code:
import arcpy import os from arcpy import env Routesworkspace = arcpy.GetParameterAsText(2) env.workspace = Routesworkspace cases = ['RCc10_3_S', 'RCc20_3_S', 'RCc30_3_S', 'RCc40_3_S', 'RCc50_3_S'] SUMDISTANCE = 0 C = 0 for fc in arcpy.ListFeatureClasses(): for case in cases: if fc.startswith(case): fields = ['DISTANCE', 'DURATION'] fieldList = arcpy.ListFields(fc) if fields in fieldList: with arcpy.da.SearchCursor(fc, fields, "FID = 0") as cursor: a = fc for row in cursor: DISTANCE = row[0] DURATION = row[1] SUMDISTANCE = SUMDISTANCE + DISTANCE C = C + 1 if C > 0: AVGDISTANCE = SUMDISTANCE / C outFile.write('' + str(int(round(AVGDISTANCE))) + '\n') else: outFile.write('' + str(0) + '\n')
Solved! Go to Solution.
Hi,
Darren is right, I overlooked that. All put together this should work:
import arcpy
import os
from arcpy import env
Routesworkspace = arcpy.GetParameterAsText(2)
env.workspace = Routesworkspace
cases = ['RCc10_3_S', 'RCc20_3_S', 'RCc30_3_S', 'RCc40_3_S', 'RCc50_3_S']
SUMDISTANCE = 0
C = 0
for fc in arcpy.ListFeatureClasses():
for case in cases:
if fc.startswith(case):
fields = ['DISTANCE', 'DURATION']
fieldList = [f.name for f in arcpy.ListFields(fc)]
if fields[0] in fieldList and fields[1] in fieldList:
with arcpy.da.SearchCursor(fc, fields, "FID = 0") as cursor:
a = fc
for row in cursor:
DISTANCE = row[0]
DURATION = row[1]
SUMDISTANCE = SUMDISTANCE + DISTANCE
C = C + 1
if C > 0:
AVGDISTANCE = SUMDISTANCE / C
outFile.write('' + str(int(round(AVGDISTANCE))) + '\n')
else:
outFile.write('' + str(0) + '\n')
That should do what your original code did except that it will ignore feature classes that do not have both columns DISTANCE and DURATION.
If you wanted to make this more generic, you should consider checking field names in case agnostic way (e.g. convert all field names to lowercase for comparison) and perhaps using set operations if you wanted to check for presence of more than 2 columns.
F.
When you say it terminates, do you get an error message? If so, what exactly does the error message say?
No i don't get any errror. The process just stops there because the third fc doesn't have these fields. That's why i put ListFields IF
Hi Kon,
The word "terminates" sounds mysterious indeed so any more details about what you can see would help.
Anyway, I think you can fix your code if you simply replace your line 13 with this:
fieldList = [f.name for f in arcpy.ListFields(fc)]
If you are not familiar with list concatenation (the suggestion above), you can write it using a map function too:
fieldList = map(lambda a: a.name, arcpy.ListFields(fc))
The bottom line is that the arcpy.ListFields function returns a list of Field objects, not list of names of fields in the feature class. To get list of names, you need to loop through the list of field objects and retrieve the name propery.
Hope this helps.
Filip.
Kral thank you for your reply, but if i replace only line 13 nothing changes, just tried.
On top of what Filip says, the logical comparison checking for both fields is incorrect. The way you have it, it is looking for a single item containing both field names to be in the list of fields. It should be:
>>> fields = ['heading','distance'] ... fieldList = [f.name for f in arcpy.ListFields("points")] ... if fields[0] in fieldList and fields[1] in fieldList: ... print "MATCH" # and do other things here ... else: ... print "NO MATCH" # and do other things here
Darren i want to calculate shp that have both these fields. If i put an if statement, if a shp doesn't have these specific fields how will the procession continue to the next?
If i understood well you mean something like that right?
for fc in arcpy.ListFeatureClasses(): for case in cases: if fc.startswith(case): fields = ['DISTANCE', 'DURATION'] fieldList = [f.name for f in arcpy.Listfields(fc)] if fields[0] in fieldList and fields[1] in fieldList: with arcpy.da.SearchCursor(fc, fields, "FID = 0") as cursor: a = fc for row in cursor: DISTANCE = row[0] DURATION = row[1]
It produces the same result
I ALSO get an error AttributeError: 'module' object has no attribute 'Listfields'
Hi,
Darren is right, I overlooked that. All put together this should work:
import arcpy
import os
from arcpy import env
Routesworkspace = arcpy.GetParameterAsText(2)
env.workspace = Routesworkspace
cases = ['RCc10_3_S', 'RCc20_3_S', 'RCc30_3_S', 'RCc40_3_S', 'RCc50_3_S']
SUMDISTANCE = 0
C = 0
for fc in arcpy.ListFeatureClasses():
for case in cases:
if fc.startswith(case):
fields = ['DISTANCE', 'DURATION']
fieldList = [f.name for f in arcpy.ListFields(fc)]
if fields[0] in fieldList and fields[1] in fieldList:
with arcpy.da.SearchCursor(fc, fields, "FID = 0") as cursor:
a = fc
for row in cursor:
DISTANCE = row[0]
DURATION = row[1]
SUMDISTANCE = SUMDISTANCE + DISTANCE
C = C + 1
if C > 0:
AVGDISTANCE = SUMDISTANCE / C
outFile.write('' + str(int(round(AVGDISTANCE))) + '\n')
else:
outFile.write('' + str(0) + '\n')
That should do what your original code did except that it will ignore feature classes that do not have both columns DISTANCE and DURATION.
If you wanted to make this more generic, you should consider checking field names in case agnostic way (e.g. convert all field names to lowercase for comparison) and perhaps using set operations if you wanted to check for presence of more than 2 columns.
F.
WORKS EXCELLENT