Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I have a script I am working on and am hitting a runtime error. I am attempting to create a list of all of the shapefiles within a root directory, then add a field to each shapefile and calculate it with the shapefile name. I am able to generate the list (converted from a dictionary) but when I attempt to add the field I encounter the error.

def main():
    try:
        import arcpy, sys, traceback, os, glob
        arcpy.env.overwriteOutput = True
        masterFolder = r"Q:\\GIS\\Field_Data\\MT"
        outputFolder = r"C:\tmp\Shp_merged"

        #collect a list of subfolders in master folder
        subfolderLst = os.listdir(masterFolder)

        #declare a dictionary where a key will be shapefile name
        #... and value a list of pathes to shapefile with this name in all subfolders
        shpDict = {}

        #loop through all subfolders
        for subfolder in subfolderLst:
            #check current subfolder and make a list of pathes to each .shp file
            shpLst = glob.glob(os.path.join(masterFolder,subfolder,'*.shp'))

            #add each shapefile path to dictionary
            for shpPath in shpLst:
                shpName = os.path.basename(shpPath)

                if not shpName in shpDict:
                    shpDict[shpName] = []
                    shpDict[shpName].append(shpPath)

                else:
                    shpDict[shpName].append(shpPath)

        shpDict = shpDict.values()

        print shpDict
        for fc in shpDict:
          arcpy.AddField_management(fc, 'shpname','text')
          arcpy.CalculateField_management(fc, 'shpname', '"'+fc+'"'+ time.strftime('%m_%d_%y'))
    #arcpy.Merge_management(fcs, 'out.shp')


    except:
        print arcpy.GetMessages()
        # Get the traceback object  '"' + wildcard + '"'
        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]

        # Concatenate information together concerning the error into a
        #   message string
        pymsg = tbinfo + "\n" + str(sys.exc_type)+ ": " + str(sys.exc_value)

        # Return python error messages for use with a script tool
        arcpy.AddError(pymsg)

        # Print Python error messages for use in Python/PythonWin
        print pymsg

if __name__ == '__main__':
    main()

The list generated looks like this:

[['Q:\\\\GIS\\\\Field_Data\\\\MT\\023N052E\\Points.shp', 'Q:\\\\GIS\\\\Field_Data\\\\MT\\023N053E\\Points.shp', 'Q:\\\\GIS\\\\Field_Data\\\\MT\\024N052E\\Points.shp']]]

and the error:

File "P:\Scripts\scratch\scratch.py", line 45, in main
    arcpy.AddField_management(fc, 'shpname','text')

<type 'exceptions.RuntimeError'>: Object: Error in executing tool

I think it has to do with cursors but being a novice I have no idea how to resolve the problem

Thanks

share|improve this question
1  
in your AddField call, change 'text' to 'TEXT' and see if that does it. –  egdetti Dec 27 '12 at 20:48
    
I suspect your choice of data structures is just down to not understanding their purpose or general unfamiliarity. I do not think a dictionary of lists is appropriate in this case (it is needless complexity). Rather, a flat list would suit your purposes fine. –  blah238 Dec 28 '12 at 4:29

4 Answers 4

It looks like one error may be from improper formatting--try replacing:

masterFolder = r"Q:\\GIS\\Field_Data\\MT"

with one of three proper ways of formatting a pathname:

masterFolder = r"Q:\GIS\Field_Data\MT"

or:

masterFolder = "Q:\\GIS\\Field_Data\\MT"

or:

masterFolder = "Q:/GIS/Field_Data/MT"
share|improve this answer
1  
Thanks for the response. I have made the changes and while it does change the values of the table I still receive the same error. –  dave_does_not_understand Dec 27 '12 at 20:35

I strongly suspect that the issue is with using a dictionary inside of the for loop.

If I am reading your code correctly you want 'shpname' to refer to an item in the shpDict list. When you pass these as arguments into the AddField_management function as it is written the computer is interpreting them as strings (literally passing 'shpname' and 'text' as arguments), which don't make sense to ArcGIS and it throws an error.

It might work better to use an iterating value in your loop (I generally use while loops for this kind of thing) and then reference the index of the list as a string in the function. Such as:

while x < len(shpDict):
     arcpy.AddField_management(fc,str(shpDict(x),"TEXT")
     x += 1

Like I said, that's just how I tend to do things like this, there may be a better way. I have had success with this technique - make sure you cast the second argument as a string using the str() function.

I hope that helps you out! If anyone has a more efficient way of accomplishing this, I'd love to hear about it!

share|improve this answer
1  
For loops are generally considered more "Pythonic" than while loops when you are working with iterables. If you need the index variable for some reason, use enumerate, which returns a tuple consisting of the current index and the current value. –  blah238 Dec 28 '12 at 4:18
    
Thanks! I'll look into that, I have been getting pretty tired of keeping track of all those x,y,z,i,j,k integers for all my while loops. I guess my C++ is showing a bit... –  Kevin Dec 28 '12 at 15:50
1  
Thanks for pointing me towards using for loops and the enumerate function! It's really cleaned up a lot of my code. –  Kevin Jan 4 '13 at 19:57

Personally, I would do the AddField and CalculateField on each featureclass as I iterated through them. I'd also use the ListFeatureClasses function of arcpy:

def main():
    try:
        import arcpy, sys, traceback, os, glob
        arcpy.env.overwriteOutput = True
        masterFolder = r"Q:\GIS\Field_Data\MT"
        outputFolder = r"C:\tmp\Shp_merged"

        #collect a list of subfolders in master folder
        arcpy.env.workspace = masterFolder
        arcpy.Listworkspaces('','Folder')

        for subfolder in subfolderLst:
            arcpy.env.workspace = subfolder
            fcLst = arcpy.ListFeatureClasses()
            for fc in fcLst:
                arcpy.AddField_management(fc, 'shpname','text')
                arcpy.CalculateField_management(fc, 'shpname', '"'+fc+'"'+ time.strftime('%m_%d_%y'))

    except:
        print arcpy.GetMessages()
        # Get the traceback object  '"' + wildcard + '"'
        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]

        # Concatenate information together concerning the error into a
        #   message string
        pymsg = tbinfo + "\n" + str(sys.exc_type)+ ": " + str(sys.exc_value)

        # Return python error messages for use with a script tool
        arcpy.AddError(pymsg)

        # Print Python error messages for use in Python/PythonWin
        print pymsg

if __name__ == '__main__':
    main()
share|improve this answer
    
Thanks for the reply Jason. Your python is much cleaner than mine. I have attempted your script and it looks like the fcList is not being populated (I think) the subfolderList populates with all of the folders in there but when I attempt to print the fcList I am not seeing anything. also none of the fields are added. –  dave_does_not_understand Dec 27 '12 at 21:19
    
Ok, that makes sense... if there are no fc's being listed in fcLst there should be no fields being added to the non-existent fc's. Try replacing the os.listdir(masterfolder) function with arcpy.Listworkspaces('','Folder'). –  Jason Dec 28 '12 at 13:23
    
Oops, you'll also need to add arcpy.env.workspace = masterFolder before you call arcpy.Listworkspaces('','Folder') –  Jason Dec 28 '12 at 14:33
    
I feel like we are almost there. I can get a list of the subfolders but the script is not rolling through the fc in those folders –  dave_does_not_understand Dec 31 '12 at 17:28
    
Make sure that the subfolder paths being fed to arcpy.env.workspace = subfolder are full paths, e.g. c:\dir\subdir and not subdir. Are the fc's getting listed at all? What type of featureclasses do you have in these folders? –  Jason Dec 31 '12 at 18:54

Here is the final code. Thanks to everybod for the help!

import  arcpy

from arcpy import env import os import time def main(): try: import arcpy, sys, traceback, os, glob, shutil arcpy.env.overwriteOutput = True log = r'Q:\1-EMPLOYEE INBOX\David\downloads\logSurveyData.txt' masterFolder = r"Q:\GIS\Field_Data\MT" outputFolder = r"C:\tmp\Shp_merged" dst = r'Q:\GIS\Field_Data\z_archive\PMM'

    #shutil.copytree(masterFolder, dst + time.strftime('%m_%d_%y'))


    #collect a list of subfolders in master folder
    arcpy.env.workspace = masterFolder
    arcpy.ListWorkspaces('','Folder')
    subfolderLst = arcpy.ListWorkspaces('','Folder')
    print subfolderLst
    for subfolder in subfolderLst:
        arcpy.env.workspace = subfolder
        fcLst = arcpy.ListFeatureClasses()

        for fc in fcLst:
            #file = fc in fcLst
            filename = "'" + arcpy.env.workspace + os.sep + fc + "'"
            print filename
            arcpy.AddField_management(fc, 'shpname','text')
            arcpy.CalculateField_management(fc, 'shpname', filename, "PYTHON" )


except:
    print arcpy.GetMessages()
        # Get the traceback object '"' + wildcard + '"'
    tb = sys.exc_info()[2]
    tbinfo = traceback.format_tb(tb)[0]


    pymsg = tbinfo + "\n" + str(sys.exc_type)+ ": " + str(sys.exc_value)


    arcpy.AddError(pymsg)


    print pymsg

    if __name__ == '__main__':
       main()
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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