【循序漸進學Python】14.數據庫的支持


純文本只能夠實現一些簡單有限的功能。如果想要實現自動序列化,也可以使用 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"

參考資料&進一步閱讀

Python Doc —— sqlite3

Python基礎教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM