2

I have a script that contains a function that fetches XML from a web service, containing a series of metadata values. The function takes a field from a feature class as criteria, queries the web service, and returns a list of metadata values associated with the submitted criteria. My intent is to update various fields in that feature class with these values, and stuff them into a dictionary so I don't have to make more web calls than necessary. I am failing at the point where it is trying to update the fields. Here is the function. It is not efficient, but it works... when I get everything else working, I'll rewrite it using elementree :)

import datetime, time, urllib, sys, arcpy

def getMetadata(id):
    iDate = ''
    iCategory = ''
    iType = ''
    svcURL = r'http://www.someurl.com/?query=" + str(id)
    localFile = r'C:\Temp\localfile.xml'
    urllib.urlretrieve(svcURL, localFile)
    readFile = open(localFile, 'r')
    for line in readFile.readlines():
        if line.find("<date_time>") > -1:
            iDatePre = line[line.find("<date_time>")+11:line.find("</date_time>")]
            iDateObject = datetime.datetime.strptime(iDatePre, '%d-%b-%y %H.%M.%S.%f %p')
            iDate = datetime.datetime.strftime(iDateObject, '%Y-%m-%d %H:%M')
        if line.find("<Category>") > -1:
            iCategory = line[line.find("<Category>")+10:line.find("</Category>")]
        if line.find("<Type>") > -1:
            iType = line[line.find("<Type>")+6:line.find("</Type>")]
        metaData = [iDate, iCategory, iType]
    readFile.close()
    return metaData

So the idea is to use da.UpdateCursor to put those values in a feature class, using row[0] as the function's criteria:

dictOfMetadata = {}

fgdb_name = 'TESTGDB'
fgdb_path = r'C:\Temp'
fgdb = fgdb_path + '\\' + fgdb_name + r'.gdb'
arcpy.env.workspace = fgdb
fdsb = 'dataset_b'

if arcpy.Exists(fdsb):
    print('Found {} dataset.'.format(fdsb))
    fcs = arcpy.ListFeatureClasses('*','',feature_dataset=fdsb)
    for cfc in fcs:
        with arcpy.da.UpdateCursor(cfc, ['ID','DTG','CAT','TYPE']) as cursor:
            for row in cursor:
                idSend = row[0]
                if dictOfMetadata.has_key(idSend):
                    print('Found local metadata for {}.'.format(idSend))
                    cursor.updateRow(row[1, 2, 3] + dictOfMetadata[idSend][0,1,2])
                else:
                    cursor.updateRow(row[1, 2, 3] + getMetadata(idSend)[0, 1, 2])
        del cursor

The error is: TypeError: list indices must be integers, not tuple

I've tried a bunch of different ways to do this but this is the closest I've gotten.

3

You are trying to call multiple indices at once, which does not work.

Comma-separated values in Python translate into a tuple, so this:

row[1, 2, 3]

actually translates to this:

row[(1, 2, 3)]

and this is not doable, as you cannot use a tuple as an index. Hence the error message.

Without being able to test this I would suggest the following:

if arcpy.Exists(fdsb):
    print('Found {} dataset.'.format(fdsb))
    fcs = arcpy.ListFeatureClasses('*','',feature_dataset=fdsb)
    for cfc in fcs:
        with arcpy.da.UpdateCursor(cfc, ['ID','DTG','CAT','TYPE']) as cursor:
            for row in cursor:
                idSend = row[0]
                if dictOfMetadata.has_key(idSend):
                    print('Found local metadata for {}.'.format(idSend))
                    row[1] = dictOfMetadata[idSend][0]
                    row[2] = dictOfMetadata[idSend][1]
                    row[3] = dictOfMetadata[idSend][2]
                    cursor.updateRow(row)
                else:
                    row[1] = getMetadata(idSend)[0]
                    row[2] = getMetadata(idSend)[1]
                    row[3] = getMetadata(idSend)[2]
                    cursor.update(row)

You can also omit the del cursor. Deleting a cursor is not necessary as the arcpy.da cursor takes care of this automatically.

If I understood correctly what you are trying to achieve then this should do the job.

  • 1
    Thanks, this does do the job in terms of the row assignments, but how do I get the values back into the dictionary? When I do dictOfMetadata[idSend][0] = row[1] under the else: part of the loop, it gives me a key error... – auslander Mar 23 '16 at 15:40
  • 1
    Oh, nevermind - I got it, I just did metaData = getMetadata(idSend) in the second loop, and then after I assign the row values I put in dictOfMetadata(idSend) = metaData. Thanks again! – auslander Mar 23 '16 at 16:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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