2016-07-13 74 views
0

我試圖寫數據掃描特定XML Document並寫一個Python程序,數據表中的SQLite數據庫。我的代碼是:的Python + SQL + XML:NoneType對象有沒有屬性「__getitem__」

import xml.etree.ElementTree as ET 
import sqlite3 

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

cur.executescript(''' 
DROP TABLE IF EXISTS Artist; 
DROP TABLE IF EXISTS Album; 
DROP TABLE IF EXISTS Track; 
DROP TABLE IF EXISTS Genre; 

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 = raw_input('Enter file name: ') 
if (len(fname) < 1) : 
    fname = 'Library.xml' 

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') 
for entry in all: 
    if (lookup(entry, 'Track ID') is None) : 
     continue 
    name = lookup(entry, 'Name') 
    artist = lookup(entry, 'Artist') 
    album = lookup(entry, 'Album') 
    genre = lookup(entry, 'Genre') 
    count = lookup(entry, 'Play Count') 
    rating = lookup(entry, 'Rating') 
    length = lookup(entry, 'Total Time') 

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

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 Album (artist_id, title) 
    VALUES (?, ?)''', (artist_id, album )) 
cur.execute('SELECT id FROM Album WHERE title = ? ', (album,)) 
album_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 REPLACE INTO Track 
    (title, album_id, genre_id, len, rating, count) 
    VALUES (?, ?, ?, ?, ?, ?)''', 
    (name, album_id, genre_id, length, rating, count)) 

conn.commit() 
conn.close() 

雖然我的代碼的其餘部分工作完全正常,段:

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

導致以下回溯:

Traceback (most recent call last): 
    File "C:\Python27\Scripts\Course 04\Wk03_Ass01.py", line 83, in <module> 
    genre_id = cur.fetchone()[0] 
TypeError: 'NoneType' object has no attribute '__getitem__' 

我完全困惑至於爲什麼會發生這種情況。引起追溯的代碼段與上面的段相同(變量名除外),這些功能完美無缺。我認爲這個錯誤可能已經發生,因爲'Genre'數據庫中的某些條目是NULL,但是我把cur.fetchone()語句放在if語句中,這也不起作用。

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

我真的很感激任何洞察到這裏出了什麼問題。謝謝!

回答

0

首先檢查是否有東西要取,然後取... if cur.rowcount == 1:是你可以用來驗證是否有單行結果。您也可以使用fetchall()並檢查返回的列表。不同的是,如果結果很大 - 您將獲取全部,因此rowcount是更好的選擇。

編輯

試着通過確切的字符串。如果可行,問題在於您將查詢傳遞給execute。根據docs,你肯定知道:

# Do this instead 
t = ('RHAT',) 
c.execute('SELECT * FROM stocks WHERE symbol=?', t) 
print c.fetchone() 
+0

cur.fetchall()不返回結果的一個長長的清單,從而預期SQL INSERT和SELECT語句肯定工作。 – thevioletsaber

+0

否則'genre_id = cur.fetchone()'代替'genre_id = cur.fetchone()[0]'返回結果,後來我得到一個不同的回溯來代替。 我試圖傳遞查詢,執行您建議的方式,但它並沒有影響結果。 – thevioletsaber

+0

好的,我修復了錯誤!儘管感謝您的幫助。 :) – thevioletsaber

1

好的,我發現了一個修復。很明顯,'流派'的數據在某些時候是空的,這就是搞砸了數據。我使用如下條件IF語句對其進行了修復:

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

if/else語句起作用!

相關問題