Python 基础学习15:数据库支持

如果要自动支持数据并发访问,允许多用户同时读写磁盘且不会导致文件损坏之类的问题,还希望能支持通过多个字段或属性进行复杂的搜索,这些需求通过纯文本的方式很难实现,此时使用标准的数据库是个好选择。

Python 数据库 API

有多种 SQL 数据库,同时也有很多对应的 Python 数据库客户端模块,为了解决模块之间接口的差异,定义了一个标准数据库 API。

全局变量

所有与 DB API 2.0 兼容的数据库模块都必须包含三个全局变量,描述了模块的特征。
全局变量:

  • apilevel:使用的 Python DB API 版本
  • threadsafety:模块的线程安全程度如何
  • paramstyle:在SQL查询中使用哪种参数风格

异常

DB API 定义了多种异常。

异常超类描述
StandardError所有异常的超类
WarningStandardError发生非致命问题时引发
ErrorStandardError所有错误条件的超类
InterfaceErrorError与接口(而不是数据库)相关的错误
DatabaseErrorError与数据库相关的错误的超类
DataErrorDatabaseError与数据相关的问题,如值不在合法的范围内
OperationalErrorDatabaseError数据库操作内部的错误
IntegrityErrorDatabaseError关系完整性遭到破坏,如键未通过检查
InternalErrorDatabaseError数据库内部的错误,如游标无效
ProgrammingErrorDatabaseError用户编程错误,如未找到数据库表
NotSupportedErrorDatabaseError请求不支持的功能,如回滚

连接和游标

要使用数据库,必须先连接到它,使用 connect 函数。
函数接受多个参数,取决于使用哪种数据库。

参数名描述是否可选
dns数据源名称,具体含义随数据库而异
user用户名
password密码
host主机名
database数据库名称

函数 connect 返回一个连接对象,表示当前到数据库的会话。
连接对象支持以下方法:

方法名描述
close()关闭连接对象。之后,连接对象及其游标将不可用
commit()提交未提交的事务——如果支持的话;否则什么都不做
rollback()回滚未提交的事务(可能不可用)
cursor()返回连接的游标对象

游标对象支持的方法比连接多。
游标对象的方法:

名称描述
callproc(name[, params])使用指定的参数调用指定的数据库过程(可选)
close()关闭游标。关闭后游标不可用
execute(oper[, params])执行一个SQL操作——可能指定参数
executemany(oper, pseq)执行指定的SQL操作多次,每次都序列中的一组参数
fetchone()以序列的方式取回查询结果中的下一行;如果没有更多的行,就返回None
fetchmany([size])取回查询结果中的多行,其中参数size的值默认为arraysize
fetchall()以序列的序列的方式取回余下的所有行
nextset()跳到下一个结果集,这个方法是可选的
setinputsizes(sizes)用于为参数预定义内存区域
setoutputsize(size[, col])为取回大量数据而设置缓冲区长度

游标对象的属性:

名称描述
description由结果列描述组成的序列(只读)
rowcount结果包含的行数(只读)
arraysizefetchmany返回的行数,默认为1

类型

为了能够与底层 SQL 数据库正确的对接,DB API 定义了一些构造函数和常量,用于提供特殊的类型和值。

DB API 构造函数和特殊值:

名称描述
Date(year, month, day)创建包含日期值的对象
Time(hour, minute, second)创建包含时间值的对象
Timestamp(y, mon, d, h, min, s)创建包含时间戳的对象
DateFromTicks(ticks)根据从新纪元开始过去的秒数创建包含日期值的对象
TimeFromTicks(ticks)根据从新纪元开始过去的秒数创建包含时间值的对象
imestampFromTicks(ticks)根据从新纪元开始过去的秒数创建包含时间戳的对象
Binary(string)创建包含二进制字符串值的对象
STRING描述基于字符串的列(如CHAR)
BINARY描述二进制列(如LONG或RAW)
NUMBER描述数字列
DATETIME描述日期/时间列
ROWID描述行ID列

并不是所有的模块都遵循上述的构造函数。

SQLite 和 PySQLite

Python 标准库内置 sqlite3 模块,实现对 SQLite 数据库的操作。

基本使用

要使用 Python 标准库中的 SQLite,首先需要导入 sqlite3 模块,然后创建到数据库文件的连接。

>>> import sqlite3
>>> conn = sqlite3.connect('demo.db')
>>> curs = conn.cursor()

只需提供一个文件名,如果指定的文件不存在将自动创建。
连接到数据后,就可以使用 cursor() 方法获取到游标。
游标可以用于执行 SQL 查询,如果修改了数据,务必通过 commit() 来提交修改。
调用 close() 方法来关闭数据库连接。

>>> conn.commit()
>>> conn.close()

数据库应用程序示例

使用现有的文件导入到 SQLite 数据库中:

import sqlite3

#数据参考格式
#~18226~^~CRACKERS,RYE,WAFERS,PLAIN~^5.00^334^9.60^0.90^4.10^80.40^22.9^1.01^40^5.94^121^334^495^557^2.80^0.461^5.366^23.8^0.1^0.427^0.289^1.581^0.569^0.271^45^0^45^45^20.0^0.00^5^0^0^1^2^0^0^245^0.80^0.0^0^5.7^0.108^0.152^0.397^0^14.2^~.5 oz~^61^~1 cup, crushed~^0

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 = 'INSERT INTO food VALUES(?,?,?,?,?,?,?,?,?,?)'
field_count = 10
for line in open('ABBREV.txt'):
    fields = line.split('^')
    vals = [convert(f) for f in fields[:field_count]]
    curs.execute(query, vals)

conn.commit()
conn.close()

搜索并处理结果程序示例:

import sqlite3, sys

conn = sqlite3.connect('food.db')
curs = conn.cursor()

query = 'SELECT * FROM food WHERE ' + 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('{}: {}'.format(*pair))
    print()

执行效果:

python food_query.py "kcal <= 100 AND fiber >= 10 ORDER BY sugar limit 1"
SELECT * FROM food WHERE kcal <= 100 AND fiber >= 10 ORDER BY sugar limit 1

id: 09216
desc: ORANGE PEEL,RAW
water: 72.5
kcal: 97.0
protein: 1.5
fat: 0.2
ash: 0.8
carbs: 25.0
fiber: 10.6
sugar: 0.0

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部