純文本只能夠實現一些簡單有限的功能。如果想要實現自動序列化,也可以使用 shelve
模塊和 pickle
模塊來實現。但是,如果想要自動的實現數據並發訪問,以及更標准,更通用的數據庫(database
)存儲方式還是使用數據庫。
1. Python 數據庫 API
很多支持SQL標准的數據庫在Python中都有對應的客戶端模塊。為了在提供相同功能(基本相同)的不同模塊之間進行切換(兼容),Python 規定了一個標准的 DB API。目前API最新版本時 2.0,具體可以參考這里:http://www.python.org/dev/peps/pep-0249/。
1.1 全局變量
任何支持2.0版本的DB API的數據庫模塊都定義了3個描述模塊特性的全局變量:
apilevel 所使用的Python DB API版本
threadsafety 模塊的線程安全級別
paramstyle 在SQL查詢中使用的參數風格
apilevel
是個字符串常量,提供正在使用API的版本號,對於DB API 2.0 版本來說
- 值可能是 ‘1.0’,
- 也可能是 ‘2.0’;
threadsafety
這這只有在使用多線程時才有參考價值,取值范圍為0~3的整數。
- 0 表示完全不共享模塊
-
- 1 表示線程本身可以共享模塊,但不對連接共享
- 3 表示模塊完全是線程安全的
paramstyle
表示在執行多次類似查詢的時候,參數是如何被拼接到SQL查詢中的:
- 'format'表示標准的字符串格式化
- 'pyformat'表示擴展的格式代碼,使用字典拼接
- 'qmark'表示使用問號
- 'numberic'表示使用 :1 或 :2 格式的字段
- 'named’表示使用 :name 格式的字段
1.2 異常
API中定義了(層次結構)一些異常類,可以通過 except 塊捕捉多種異常。如果想要知道更多DB API異常的想想可以參考這里:http://www.python.org/dev/peps/pep-0249/#exceptions,下面是DB API中使用的異常:
===============================================================================
異常 超類 描述
===============================================================================
StandarError 所有異常的泛型基類
Waring StandarError 在非致命錯誤發生時引發
Error StandarError 所有錯誤條件的泛型超類
InterfaceError Error 關於接口而非數據庫的錯誤
DatabaseError Error 與數據庫相關的錯誤的基類
DataError DatabaseError 與數據庫相關的問題,比如值超出范圍
OperationalError DatabaseError 數據庫內部操作錯誤
IntegrityError DatabaseError 關系完整性受到影響,比如鍵檢查失敗
InternalError DatabaseError 數據庫內部錯誤,比如非法游標
ProgramningError DatabaseError 用戶編程錯誤,比如未找到表
NotSupportedError DatabaseError 請求不支持的特性(比如回滾)
1.3 連接和游標
使用 connect
函數連接到數據庫,該函數有多個參數,具體使用方法取決於對應的數據庫。下面是具體的參數含義(使用時推薦使用關鍵字參數的方式):
==================================================
參數名 描述
==================================================
dsn 數據庫源名稱,給出參數表示數據庫依賴(必選)
user 用戶名(可選)
passowrd 密碼(可選)
host 主機名(可選)
database 數據庫名(可選)
函數返回連接對象,該對象表示目前和數據庫的會話,對象支持的方法如下:
=============================================================
方法名 描述
=============================================================
close() 關閉連接之后,連接對象和它的游標均不可用
commit() 如果支持的話就提交掛起事務,否則不可用
rollback() 回滾掛起的事務
cursor() 返回連接的游標對象
rollback
方法如果使用的數據庫支持的話,就會撤銷所有未提交的事務。而 cursor
方法則返回一個游標對象,可以通過游標執行SQL查詢並檢查結果。游標比連接支持更多方法,也更加易用,下面是游標方法的概述:
====================================================================================
名稱 描述
====================================================================================
callproc(name[, params]) 使用給定的名稱和參數(可選)調用以命名的數據庫程序
close() 關閉游標后,游標不可用
execute(oper[, params]) 執行SQL操作,可選的參數
executemany(oper, pseq) 對序列中的每個參數執行SQL操作
fetchone() 把查詢結果集中的下一行保存為序列或者None
fetchmany([size]) 獲取查詢的結果集中的多行,默認尺寸為arraysize
fetchall() 將所有(剩余)的行作為序列的序列
nextset() 跳至下一個可用的結果集(可選)
setinputsizes(sizes) 為參數預先定義的內存區域
setoutputsize(size[, col]) 為獲取的大數據庫值設定緩沖區尺寸
游標對象還包含一些特性:
==================================================
名稱 描述
==================================================
description 結果列描述的序列,只讀
rowcount 結果中的行數,只讀
arraysize fetchmany中返回的行數,默認為1
1.4 類型
DB API 定義了Python中的類型和數據庫類型的對應關系。通過特殊的類型和值的構造函數以及常量(單例模式),如下(一些模塊可能並不是完全按照這些定義):
==================================================
名稱 描述
==================================================
Date(year, month, day) 創建保存日期值的對象
Time(hour, minute, second) 創建保存時間值的對象
Timestamp(y, mon, d, h, min, s) 創建保存時間戳的對象
DateFromTicks(ticks) 創建保存自新紀元以來的秒數的對象
TimeFromTicks(ticks) 創建保存來自秒數的時間值的對象
TimestampFromTicks(ticks) 創建保存來自秒數的時間戳值的對象
Binary(string) 創建保存二進制字符串值的對象
STRING 描述二進制列(比如LONG或RAW)
BINARY 描述數字列
MUMBER 描述數字列
DATETIME 描述日期/時間列
ROWID 描述行ID列
2. SQLite 和PySQLite
SQLite是一個小型的數據庫引擎,它不基於集中式數據庫存儲機制,而是直接作用於本地文件。在Python 2.5 之后,SQLite 的包裝(PySQLite)已經被包含在標准庫中了(在最新的Python版本中已經包含了SQLite數據庫了,並不需要單獨安裝)。
2.1 簡單示例
將SQLite作為名為sqlite3的模塊導入,即可創建一個數據庫文件(不存在則創建,可指定路徑),並連接到數據庫,下面是一個簡單的示例:
# -- coding:utf-8 --
import sqlite3
conn = sqlite3.connect('myDatabase.db')
curs = conn.cursor() # 獲得游標
conn.commit() # 提交更改
conn.close() # 關閉連接
2.2 創建和填充表
通過下面的示例來學習如果創建和向表中插入數據,在這里使用的數據庫是基於USDA營養數據庫實驗室提供的文本格式的數據庫,在這里使用的文件地址是:http://sr23-nutrient-calculator.googlecode.com/svn-history/r9/trunk/ABBREV.txt,示例如下:
import sqlite3
def convert(value):
if value.startswith('~'):
return value.strip('~')
if not value:
value = '0'
return float(value)
conn = sqlite3.connect('food.db')
curs = conn.cursor()
curs.execute('''
CREATE TABLE food(
id TEXT PRIMARY KEY,
desc TEXT,
water FLOAT,
kcal FLOAT,
protein FLOAT,
fat FLOAT,
ash FLOAT,
carbs FLOAT,
fiber FLOAT,
sugar FLOAT
)
''')
query = r'INSERT INTO food VALUES(?,?,?,?,?,?,?,?,?,?)'
for line in open('ABBREV.txt'):
fields = line.split('^')
vals = [convert(f) for f in fields[0:10]]
curs.execute(query,vals)
conn.commit()
conn.close()
2.3 搜索和處理結果
查詢數據庫內容只需要創建連接,並獲得該連接的游標即可,通過 execute
方法執行SQL查詢,使用 fetchall
等方法提取結果,如下所示:
# food_query.py
import sqlite3,sys
conn = sqlite3.connect('food.db')
curs = conn.cursor()
query = 'select * from food WHERE %s' % sys.argv[1]
print query
curs.execute(query)
names = [f[0] for f in curs.description]
for row in curs.fetchall():
for pair in zip(names,row):
print '%s: %s'% pair
print
運行程序,通過命令行傳遞查詢參數:
python food_query.py "kcal <=100 AND fiber >= 10 ORDER BY sugar"