python sqlite3 row_factory and text_factory

row_factory

主要功能是改變sqlite抓取到資料,回傳的output的格式。

例如原先的output type是tuple:

cursor.execute("select 1 as a")
result = cursor.fetchone()
print type(result) is tuple

如果要使用dict,可以覆蓋row_factory

import sqlite3

def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

con = sqlite3.connect(":memory:")
con.row_factory = dict_factory
cur = con.cursor()
cur.execute("select 1 as a")
print cur.fetchone()["a"]

其實也可以直接使用官方預設的sqlite3/336/)./336/)Row

con.row_factory = sqlite3.Row
cur = con.cursor()
cur.execute("select 1 as a")
result = cur.fetchone()
#1
print result["a"]
#1
print result[0]
#1
print len( result )
#["a"]
print result.keys()

text_factory

只要query出來的內容是text,就會經過這個function,可以用於字串編碼轉換,當然也可以利用這個方式去修改內容.。

以下是簡單example:

import sqlite3

con = sqlite3.connect(":memory:")
cur = con.cursor()

AUSTRIA = u"\xd6sterreich"

cur.execute("select ?", (AUSTRIA,))
row = cur.fetchone()

#<type 'unicode'>
print type(row[0])

con.text_factory = str
cur.execute("select ?", (AUSTRIA,))
row = cur.fetchone()

#<type 'str'>
print type(row[0])

con.text_factory = lambda x: unicode(x, "utf-8", "ignore")
cur.execute("select ?", ("this is latin1 and would normally create errors" +
                         u"\xe4\xf6\xfc".encode("latin1"),))
row = cur.fetchone()

#<type 'unicode'>
print type(row[0])

con.text_factory = sqlite3.OptimizedUnicode
cur.execute("select ?", (AUSTRIA,))
row = cur.fetchone()

#<type 'unicode'>
print type(row[0])

con.text_factory = sqlite3.OptimizedUnicode
cur.execute("select ?", ("test",))
row = cur.fetchone()

#<type 'str'>
print type(row[0])

其中sqlite3.OptimizedUnicode會自動偵測轉換不同編碼,如果字串是 ASCII可以顯示的,將會回傳str,否則回傳unucode。

 

題外話:

如果發現import sqlite3找不到module…,讓就必須在重新編譯python…,在編譯之前先執行:

sudo apt-get install libsqlite3-dev

在重新編譯python安裝即可。