Error accessing dictionary values

2266
4
Jump to solution
12-08-2014 10:10 AM
Zeke
by
Regular Contributor III

In the code below, line 14,  'alias = dict[fld.name]', always throws an exception. I don't see why; printing out fld.name works just fine. Also, the exception message is the field name printing correctly.

Printing the dictionary keys and values also works fine. The ultimate goal is to get a string to set as the field alias using AlterField. Thanks.

with arcpy.da.SearchCursor(metatable, metaflds) as rows:
        for row in rows:
            if not moe in row[1]:
                fn = row[1].replace(' ', '')
                fn = fn.replace(est, '')
                dict[row[0]] = fn

    # Get list of tables to add alias to
    tbls = arcpy.ListTables()
    for tbl in tbls:
        tblflds = arcpy.ListFields(tbl)
        for fld in tblflds:
            try:
                alias = dict[fld.name]   # exception raised here
                print(alias)
            except Exception as e:
                import traceback
                import sys
                tb = sys.exc_info()[2]
                print('Oh no!')
                print("Line {0}".format(tb.tb_lineno))
                print(e.message)
0 Kudos
1 Solution

Accepted Solutions
Zeke
by
Regular Contributor III

Yes, that's what it would mean, except I can see it's there. Printing the keys and values prints the correct sequences.

Anyway, I got it to work by changing alias = dictflds[fld.name] to ‌alias = dictflds.get(fld.name, 'None')‌. No idea why the first method didn't work if the second does, but I've spent enough time on this. Thanks for the help, appreciate it.

View solution in original post

4 Replies
JoshuaBixby
MVP Esteemed Contributor

A few things.  What is the error message, specifically?  Second, it seems you are naming your dictionary 'dict', which shadows the built-in dict constructor.  Although shadowing a built-in doesn't break the code, per se, it does make it more difficult to read and therefore more prone to errors.  Third, the code snippet doesn't show the dictionary object being created, is that just handled earlier?

0 Kudos
Zeke
by
Regular Contributor III

Thanks Joshua. I changed the name of the dictionary to dictflds. The error I get if I try to access the value outside of the try block is KeyError: u'B01001e1', and the error when in the try block reads Line 45, B01001e1, where the line number is wherever I first try to access the dictionary value and B01001e1 is a valid field name. It's not that particular value that's a problem; the error occurs for every field. I've tried enclosing it in str(), setting it to a variable both when accessing it and setting the key, no luck. If I just print fld.name, works fine. Full code (minus header comments) below.

import arcpy, os
from arcpy import env
env.workspace = r'K:\Projects\Other Depts\Planning\Lori_Census\Census.gdb'

def main():
    metatable = 'BG_Metadata_2012'
    metaflds = ('Short_Name', 'Full_Name')
    est = '--(Estimate)'
    moe = 'Margin of Error'
    dictflds = {}

    # Get dictionary of short names and corresponding full names from metadata
    # table, skipping moe fields and removing whitespace and estimate text from
    # full name.
    with arcpy.da.SearchCursor(metatable, metaflds) as rows:
        for row in rows:
            if not moe in row[1]:
                fn = row[1].replace(' ', '')
                fn = fn.replace(est, '')
                dictflds[row[1]] = fn

    for k, v in dictflds.iteritems()
        print(' : '.join([k, v])   # works fine

    # Get list of tables to add alias to
    tbls = arcpy.ListTables()
    for tbl in tbls:
        tblflds = arcpy.ListFields(tbl)

        for fld in tblflds:
            try:
                print(fld.name)   # works fine
                alias = dictflds[fld.name]   # exception raised here
                print(alias)
                print(' : '.join[tbl, fld.name, alias])
                arcpy.AlterField_management(tbl, fld, new_field_alias=alias)

            except Exception as e:
                import traceback
                import sys
                tb = sys.exc_info()[2]
                print('Oh no!')
                print("Line {0}".format(tb.tb_lineno))
                print(e.message)   # this prints the fld.name value

if __name__ == '__main__':
    main()
0 Kudos
JoshuaBixby
MVP Esteemed Contributor

The Key Error outside of the Try block is the crux of the issue.  As far as the interpreter is concerned, there is no key corresponding to the value you are giving it, so it returns a Key Error, i.e., u'B01001e1' is not key, period.  At this point, are there any differences in capitalization or white spaces?  I don't think it is an text encoding issue.  Trying printing your dictionary (print dictflds) and double checking that there is in fact a u'B01001e1' key.

0 Kudos
Zeke
by
Regular Contributor III

Yes, that's what it would mean, except I can see it's there. Printing the keys and values prints the correct sequences.

Anyway, I got it to work by changing alias = dictflds[fld.name] to ‌alias = dictflds.get(fld.name, 'None')‌. No idea why the first method didn't work if the second does, but I've spent enough time on this. Thanks for the help, appreciate it.