Home > Mobile >  SQL in python TypeError: 'NoneType' object is not subscriptable in genre
SQL in python TypeError: 'NoneType' object is not subscriptable in genre

Time:03-20

When I run the code it says type error in line where "genre_id = cur.fetchone()[0]", I dont know what is happening. It makes sense to me but I dont see where is wrong. It starts doing the list but stops in a part. I tried changin the order but it doesnt makes sense, I saw the solution that is basically the same but different names and... it works but doesnt understand why mine doesnt


import xml.etree.ElementTree as ET
import sqlite3

conn = sqlite3.connect('trackdb.sqlite')
cur = conn.cursor()

# Make some fresh tables using executescript()
cur.executescript('''

DROP TABLE IF EXISTS Artist;
DROP TABLE IF EXISTS Genre;
DROP TABLE IF EXISTS Album;
DROP TABLE IF EXISTS Track;
CREATE TABLE Artist (
    id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    name    TEXT UNIQUE
);
CREATE TABLE Genre (
    id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    name    TEXT UNIQUE
);
CREATE TABLE Album (
    id  INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
    artist_id  INTEGER,
    title   TEXT UNIQUE
);
CREATE TABLE Track (
    id  INTEGER NOT NULL PRIMARY KEY
        AUTOINCREMENT UNIQUE,
    title TEXT  UNIQUE,
    album_id  INTEGER,
    genre_id  INTEGER,
    len INTEGER, rating INTEGER, count INTEGER
);
''')


fname = input('Enter file name: ')
if ( len(fname) < 1 ) : fname = 'Library.xml'

# <key>Track ID</key><integer>369</integer>
# <key>Name</key><string>Another One Bites The Dust</string>
# <key>Artist</key><string>Queen</string>
def lookup(d, key):
    found = False
    for child in d:
        if found : return child.text
        if child.tag == 'key' and child.text == key :
            found = True
    return None

stuff = ET.parse(fname)
all = stuff.findall('dict/dict/dict')
print('Dict count:', len(all))
for entry in all:
    if ( lookup(entry, 'Track ID') is None ) : continue

    name = lookup(entry, 'Name')
    artist = lookup(entry, 'Artist')
    genre = lookup(entry, 'Genre')
    album = lookup(entry, 'Album')


    if name is None or artist is None or album is None :
        continue

    print(name, artist, album, genre) #cambiar aber

    cur.execute('''INSERT OR IGNORE INTO Artist (name)
        VALUES ( ? )''', ( artist, ) )
    cur.execute('SELECT id FROM Artist WHERE name = ? ', (artist, ))
    artist_id = cur.fetchone()[0]

    cur.execute('''INSERT OR IGNORE INTO Genre (name)
        VALUES ( ? )''', ( genre, ) )
    cur.execute('SELECT id FROM Genre WHERE name = ? ', (genre, ))
    genre_id = cur.fetchone()[0]

    cur.execute('''INSERT OR IGNORE INTO Album (title, artist_id)
        VALUES ( ?, ? )''', ( album, artist_id ) )
    cur.execute('SELECT id FROM Album WHERE title = ? ', (album, ))
    album_id = cur.fetchone()[0]

    cur.execute('''INSERT OR REPLACE INTO Track
        (title, album_id, genre_id)
        VALUES ( ?, ?, ?)''',
        (name, album_id, genre_id) )

    conn.commit()

CodePudding user response:

The error

TypeError: 'NoneType' object is not subscriptable in genre

means that your line

    cur.execute('SELECT id FROM Genre WHERE name = ? ', (genre, ))

didn't return any rows.

Did you intend to pass a tuple to the SELECT?

CodePudding user response:

Your lookup function can return a string or None. When it returns None, you will insert a NULL value. In most SQL implementations, including SQLite, comparing anything to a NULL will result in a NULL, which is not true. In other words, the query you immediately follow up with to find the id will not find a row, since no row will satisify the equation "genre = NULL".

Hence your failure. The call to .fetchone() returns None since there is no matching row, and you try to index into None, and it fails.

You'll need to special case the NULL value with something like this:

cur.execute('''INSERT OR IGNORE INTO Genre (name)
        VALUES ( ? )''', ( genre, ) )
if genre is None:
    cur.execute('SELECT id FROM Genre WHERE name IS NULL ')
else:
    cur.execute('SELECT id FROM Genre WHERE name = ? ', (genre, ))
genre_id = cur.fetchone()[0]
  • Related