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]