>>> from helper import info; info()
页面更新时间: 2020-07-05 19:24:05
操作系统/OS: Linux-4.19.0-9-amd64-x86_64-with-debian-10.4 ;Python: 3.7.3
Python 数据库 API¶
前面说过,有各种SQL数据库可供选择,其中很多都有相应的Python客户端模块(有些数据库甚至有多个)。 所有数据库的大多数基本功能都相同,因此从理论上说,对于使用其中一种数 据库的程序,很容易对其进行修改以使用另一种数据库。 问题是即便不同模块提供的功能大致相 同,它们的接口(API)也是不同的。 为解决Python数据库模块存在的这种问题,人们一致同意开发一个标准数据库API(DB API)。 这个API的最新版本(2.0)是在PEP 249(Python Database API Specification v2.0)中定义的, 网址为 http://python.org/peps/pep-0249.html 。
本节概述有关该API的基础知识。这里不会涉及其可选部分,因为它们并不适用于所有数据 库。有关该API的详细信息,可参阅前面提到的PEP,也可参阅Python官方维基百科中的数据库编 程指南( http://wiki.python.org/moin/DatabaseProgramming )。如果你对这个API的细节不感兴趣, 可跳过本节。
全局变量¶
所有与DB API2.0兼容的数据库模块都必须包含三个全局变量,它们描述了模块的特征。这 样做的原因是,这个API设计得很灵活,无需进行太多包装就能配合多种不同的底层机制使用。 如果要让程序能够使用多种不同的数据库,可能会比较麻烦,因为需要考虑众多不同的可能性。 在很多情况下,一种更现实的做法是检查这些变量,看看给定的模块是否是程序能够接受的。如 果不是,就显示合适的错误消息并退出或者引发异常。表13-1总结了这些全局变量。
Python DB API的模块属性
变 量 名 | 描 述 |
---|---|
apilevel | 使用的Python DB API版本 |
threadsafety | 模块的线程安全程度如何 |
paramstyle | 在SQL查询中使用哪种参数风格 |
API级别(apilevel)是一个字符串常量,指出了使用的API版本。DB API 2.0指出,这个变 量的值为’1.0’或’2.0’。如果没有这个变量,就说明模块不与DB API 2.0兼容,应假定使用的是 DB API 1.0。编写代码时,允许这个变量为其他值也没有害处,因为说不定什么时候DB API 3.0 就出来了。
线程安全程度(threadsafety)是一个0~3(含)的整数。0表示线程不能共享模块,而3表 示模块是绝对线程安全的。1表示线程可共享模块本身,但不能共享连接(参见13.1.3节),而2 表示线程可共享模块和连接,但不能共享游标。如果你不使用线程(在大多数情况下可能不会是这样的),就根本不用关心这个变量。
参数风格(paramstyle)表示当你执行多个类似的数据库查询时,如何在SQL查询中插入参数。’format’表示标准字符串格式设置方式(使用基本的格式编码),如在要插入参数的地方插 入%s。’pyformat’表示扩展的格式编码,即旧式字典插入使用的格式编码,如%(foo)s。除这些 Python风格外,还有三种指定待插入字段的方式:’qmark’表示使用问号,’numeric’表示使用:1 和:2这样的形式表示字段(其中的数字是参数的编号),而’named’表示使用:foobar这样的形式表示字段(其中foobar为参数名)。如果你觉得参数样式令人迷惑,也不用担心。编写简单程序时, 不会用到它们。如果需要明白特定的数据库是如何处理参数的,可参阅相关的文档。
异常¶
DB API定义了多种异常,让你能够细致地处理错误。然而,这些异常构成了一个层次结构, 因此使用一个except块就可捕获多种异常。当然,如果你觉得一切都正常运行,且不介意出现不 太可能出现的错误时关闭程序,可以根本不考虑这些异常。
表13-2说明了这个异常层次结构。异常应该在整个数据库模块中都可用。有关这些异常的深 入描述,请参阅DB API规范(前面提到的PEP)。
表13-2 Python DB API指定的异常
异 常 | 超 类 | 描 述 |
---|---|---|
tandardError | 所有异常的超类 | |
arning | StandardError | 发生非致命问题时引发 |
rror | StandardError | 所有错误条件的超类 |
nterfaceError | Error | 与接口(而不是数据库)相关的错误 |
atabaseError | Error | 与数据库相关的错误的超类 |
ataError | DatabaseError | 与数据相关的问题,如值不在合法的范围内 |
perationalError | DatabaseError | 数据库操作内部的错误 |
ntegrityError | DatabaseError | 关系完整性遭到破坏,如键未通过检查 |
nternalError | DatabaseError | 数据库内部的错误,如游标无效 |
rogrammingError | DatabaseError | 用户编程错误,如未找到数据库表 |
otSupportedError | DatabaseError | 请求不支持的功能如回滚 |
连接和游标¶
要使用底层的数据库系统,必须先连接到它,为此可使用名称贴切的函数connect。这个函 数接受多个参数,具体是哪些取决于要使用的数据库。作为指南,DB API定义了表13-3所示的参 数。推荐将这些参数定义为关键字参数,并按表13-3所示的顺序排列。这些参数都应该是字符串。
表13-3 函数connect的常用参数
参数名 | 描述 | 是否可选 |
---|---|---|
dsn | 数据源名称,具体含义随数据库而异 | 否 |
user | 用户名 | 是 |
password | 用户密码 | 是 |
host | 主机名 | 是 |
database | 数据库名称 | 是 |
13.2.1节和第26章提供了函数connect的具体使用示例。 函数connect返回一个连接对象,表示当前到数据库的会话。连接对象支持表13-4所示的方法。
表13-4 连接对象的方法
方法名 | 描述 |
---|---|
close() | 关闭连接对象。之后,连接对象及其游标将不可用 |
commit() | 提交未提交的事务——如果支持的话;否则什么都不做 |
rollback() | 回滚未提交的事务(可能不可用) |
cursor() | 返回连接的游标对象 |
方法 rollback 可能不可用,因为并非所有的数据库都支持事务(事务其实就是一系列操作)。 可用时,这个方法撤销所有未提交的事务。
方法 commit 总是可用的,但如果数据库不支持事务,这个方法就什么都不做。关闭连接时, 如果还有未提交的事务,将隐式地回滚它们——但仅当数据库支持回滚时才如此!如果你不想依 赖于这一点,应在关闭连接前提交。只要提交了所有的事务,就无需操心关闭连接的事情,因为 作为垃圾被收集时,连接会自动关闭。然而,为安全起见,还是调用 close 吧,因为这样做不需 要长时间敲击键盘。
说到方法 cursor ,就必须说说另一个主题:游标对象。你使用游标来执行SQL查询和查看结 果。游标支持的方法比连接多,在程序中的地位也可能重要得多。表13-5概述了游标的方法,而 表13-6概述了游标的属性。
表13-5 游标对象的方法
名称 | 描述 |
---|---|
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]) | 为取回大量数据而设置缓冲区长度 |
表13-6 游标对象的属性
名 称 | 描 述 |
---|---|
description | 由结果列描述组成的序列(只读) |
rowcount | 结果包含的行数(只读) |
arraysize | fetchmany返回的行数,默认为1 |
有些方法将在本章后面详细讨论,还有一些(如setinputsizes和setoutputsizes)则不会讨论。有关这些方法的详细信息,请参阅前面提到的PEP。
类型¶
对于插入到某些类型的列中的值,底层SQL数据库可能要求它们满足一定的条件。为了能够 与底层SQL数据库正确地互操作,DB API定义了一些构造函数和常量(单例),用于提供特殊的 类型和值。例如,要在数据库中添加日期,应使用相应数据库连接模块中的构造函数Date来创建 它,这让连接模块能够在幕后执行必要的转换。每个模块都必须实现表13-7所示的构造函数和特 殊值。有些模块可能没有完全遵守这一点。例如,接下来将讨论的模块sqlite3就没有导出表13-7 中特殊值(从STRING到ROWID)。
表13-7 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列 |