Search code examples
pythondatabasesqlitepython-3.xgeonames

geonames-dump to sqlite python error 'dict_items' object does not support indexing


I'm getting this error when running the python code from below

'dict_items' object does not support indexing

https://github.com/commodo/geonames-dump-to-sqlite/blob/master/geonames_dump_to_sqlite.py

what the code does is get files from geonames and put the results in a sqlite database.

it runs fine until creating the tables

def create_tables(cur):
    '''
    Create empty tables which will be populated later.
    '''
    for table_name in TABLE_MAPPINGS.values():
        cur.execute('DROP TABLE IF EXISTS %s' % table_name)
        table_fields = [ "%s %s" % table_field.listitems()[0] for table_field in TABLE_FIELDS ]
        cur.execute('CREATE TABLE %s (%s)' % (table_name, ','.join(table_fields)))

error specifics:

  line 111, in <listcomp>
    table_fields = [ "%s %s" % table_field.items()[0] for table_field in TABLE_FIELDS ]
TypeError: 'dict_items' object does not support indexing

Solution

  • In Python 3, dict.items() returns a dictionary view, not a list object. You can convert it to a list here (there is only one key and value per TABLE_FIELDs entry anyway):

    table_fields = [ "%s %s" % list(table_field.items())[0] for table_field in TABLE_FIELDS ]
    

    Later on, you'll run into the same problem, because the code tries to do the same to table_field.keys():

    table_fields = [ "%s" % list(table_field.keys()[0] for table_field in TABLE_FIELDS ]
    

    Change that to:

    table_fields = [ "%s" % list(table_field)[0] for table_field in TABLE_FIELDS ]
    

    Both uses could also be replaced with next(iter(table_field.items())) and next(iter(table_field)), respectively.

    I have no idea why the author used a list of one-key dictionaries there; it'd have been easier if the code used tuples instead:

    TABLE_FIELDS = [('parentid',        'integer'),
                    ('geonameid',       'integer'),
                    ('name',            'text'),
                    # etc.
    

    then use % table_field and % table_field[0] respectively.

    There may be other Python 3 incompatibilities in that script, however.