【本期導(dǎo)讀】使用PySQLite連接SQLite遇到的問題與解決方法
Python要操作SQLite可以使用Pyslqite模塊,最新的模塊可以去
www.pysqlite.org下載,當初下載的時候順便簡單看了看usage-guide(
http://initd.org/pub/software/pysqlite/doc/usage-guide.html),覺得挺簡單的,沒有仔細研究便開始考慮編寫,我考慮把sqlite的訪問寫成一個類,在類的初始化和銷毀時候分別建立連接和關(guān)閉連接,然后再添加一個執(zhí)行sql語句的方法,由于傳入的sql可能沒有返回值也可能有返回值,而返回的值可能是單列值也可能是多條記錄,基于這種復(fù)雜情況,就讓這個方法返回一個列表,管它返回什么,通通加到列表中然后返回,我覺得在這一點上,python比其它語言方便多了。下面是這個類:
#!/usr/bin/python
#?-*-?coding:?UTF-8?-*-
#?$Id:?dbconnect.py?8?2006-04-08?14:21:32Z?Administrator?$
import?ConfigParser
import?locale
from?pysqlite2?import?dbapi2?as?sqlite

class?SqliteConnection:
????
????def?__init__(self,dbname):
????????"""
????????初始化數(shù)據(jù)庫連接
?????????"""????????
????????self.conn?=?sqlite.connect(dbname)
????def?execute(self,sql):
????????"""
????????執(zhí)行傳入的sql語句,返回一個元組或者None
????????"""
????????self.cu=self.conn.cursor()
????????self.cu.execute(sql)
????????self.conn.commit()

????????self.rows=[]
????????for?self.row?in?self.cu:
????????????self.rows.append(self.row)
????????return?self.rows
????def?__del__(self):
????????"""關(guān)閉數(shù)據(jù)庫連接"""
????????self.conn.close()
def?test():
????"""測試方法"""
????config=ConfigParser.ConfigParser()
????config.read('config')
????dbname=config.get('SQLiteDB','filename')
????
????test=?SqliteConnection(":memory:")
????test.execute("create?table?person(lastname,?firstname)")
????test.execute("insert?into?person(lastname,firstname)?values('三','張')")
????test.execute("insert?into?person(lastname,firstname)?values('四','李')")
if?__name__=='__main__':
????test()之前簡單試過一下訪問sqlite一切OK,可是當然運行一下這個類時,結(jié)果居然出錯了:
Traceback (most recent call last):
? File "D:\source\dbconnect.py", line 49, in
?
??? test()
? File "D:\source\dbconnect.py", line 42, in
test
??? temp=test.execute("select * from person")
? File "D:\source\dbconnect.py", line 22, in
execute
??? self.cu.execute(sql)
pysqlite2.dbapi2.OperationalError: Could not decode to UTF-8 column firstname wi
th text 張
既然出錯了,那么大概是這幾種情況:
1.pysqlite不支持中文
2.sqlite不支持中文
3.代碼出了問題
出錯之后,經(jīng)過測試,排除第1和2兩種可能,
于是我仔細簡單代碼,可還是沒有找到出錯原因,于是想查看pysqlite源代碼,可是他的代碼是封閉在一個pyd的二進制文件中的,沒辦法查看,于是去下載pysqlite的源代碼,拿到源代碼后在pysqlite-2.2.0\src\cursor.c這個代碼中找到了OperationalError錯誤類型,知道原來是字符轉(zhuǎn)換時出這個錯。于是我就試試將返回值轉(zhuǎn)為可是我弄了很久都沒有弄好,在網(wǎng)上google一下也沒有找到這方面的資料,找了一天了也沒有找到解決的辦法,無奈之下險些泄氣。雖然之前看過pysqlite文檔,但看得不仔細,只是簡單瀏覽,當時只是想這東西應(yīng)該挺簡單的,例子也夠詳細就沒有花太多時間去看文檔,為得也是節(jié)省時間。現(xiàn)在遇到問題了,還是老老實實仔細看看pysqlite文檔吧。果然不枉我滴著眼藥水把它看完,終于找到原因了,原來pysqlite中有個
con.text_factory可以解決這個問題,這個參數(shù)默認值是unicode ,現(xiàn)在只需要把它設(shè)置成str就可以了:


?1
#!/usr/bin/python
?2
#?-*-?coding:?UTF-8?-*-
?3
#?$Id:?dbconnect.py?8?2006-04-08?14:21:32Z?Administrator?$
?4
import?ConfigParser
?5
import?locale
?6
from?pysqlite2?import?dbapi2?as?sqlite
?7
?8
class?SqliteConnection:
?9
????
10
????def?__init__(self,dbname):
11
????????"""
12
????????初始化數(shù)據(jù)庫連接
13
????????"""????????
14
????????self.conn?=?sqlite.connect(dbname)
15
????????self.conn.row_factory?=?sqlite.Row?#加上這句才能使用列名來返回值
16
????????self.conn.text_factory=str?#加上這一句,否則出現(xiàn)"Could?not?decode?to?UTF-8?column"錯誤
17
????def?execute(self,sql):
18
????????"""
19
????????執(zhí)行傳入的sql語句,返回一個元組或者None
20
????????"""
21
????????self.cu=self.conn.cursor()
22
????????self.cu.execute(sql)
23
????????self.conn.commit()
24
25
????????self.rows=[]
26
????????for?self.row?in?self.cu:
27
????????????self.rows.append(self.row)
28
????????return?self.rows
29
????def?__del__(self):
30
????????"""關(guān)閉數(shù)據(jù)庫連接"""
31
????????self.conn.close()
32
def?test():
33
????"""測試方法"""
34
????config=ConfigParser.ConfigParser()
35
????config.read('config')
36
????dbname=config.get('SQLiteDB','filename')
37
????
38
????test=?SqliteConnection(":memory:")
39
????test.execute("create?table?person(lastname,?firstname)")
40
????test.execute("insert?into?person(lastname,firstname)?values('三','張')")
41
????test.execute("insert?into?person(lastname,firstname)?values('四','李')")
42
????temp=test.execute("select?*?from?person")
43
????print?temp
44
????encoding?=?locale.getdefaultlocale()[1]
45
????print?str('第一條記錄:').decode(encoding)+str(temp[0][1]).decode(encoding)+str(temp[0][0]).decode(encoding)
46
????print?str('第二條記錄:').decode(encoding)+str(temp[1][1]).decode(encoding)+str(temp[1][0]).decode(encoding)
47
????assert?str(temp[0][1]).decode(encoding)+str(temp[0][0]).decode(encoding)==str("張三").decode(encoding)
48
if?__name__=='__main__':
49
????test()至此總算解決了這個困擾我一天的問題了。
【下期提示】開始學(xué)習(xí)wxPython,體驗一下它的強大界面表現(xiàn)力。