对于MySQL、Access、Oracle、Sybase、Microdoft SQL Server、SQLite等关系型的数据库,Python都提供了ODBC接口。
Python提供了一个标准接口用于访问关系型的数据库,即Python DB Application Programming Interface(Py-DBAPI)。每种数据库API都需要一个Py-DBAPI封装的实现,几乎所有的数据库接口都有对应的是是实现方法,同时,Python还内置了用于存储和获取数据的工具。
官方文档:https://wiki.python.org/moin/DatabaseInterfaces
一、struct模块
1.1 介绍
官方文档:https://docs.python.org/2/library/struct.html#struct-format-strings
平面数据库(flat database)是文本数据或二进制数据文件。
打开文本数据文件,使用open() 函数就可以。
打开二进制数据文件,使用struct模块,需要用’wb’,’rb’以二进制(字节流)写,读的方式来处理文件;
链接:https://blog.csdn.net/shudaqi2010/article/details/78133120?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-10&spm=1001.2101.3001.4242
struct模块可以处理和操作与系统无关的二进制数据文件,只适合处理小型文件,如果是大型文件,需要用array模块处理。
struct模块将二进制文件的数据与Python结构进行转换,通常是使用C语音所写的接口来完成。
1.2 方法
| 方法 | 说明 |
|---|---|
| struct.pack(fmt, v1, v2, …) | 按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回 |
| struct.pack_into(fmt,buffer,offset,v1,v2,… ) | 根据给定的格式(fmt),将数据转换成字符串(字节流),并将字节流写入offset开始的buffer中。(buffer为可写的缓冲区,可用array模块) |
| struct.unpack(fmt,string | 根据给定的格式解压缩字符串,结果是一个元组,即使它只包含一个项目。该字符串必须完全包含该格式所需的数据量(必须等于) |
| struct.unpack_from(fmt,buffer [,offset = 0 ] ) | 根据给定的格式解压缩缓冲区。结果是一个元组,即使它只包含一个项目。 |
| struct.calcsize(fmt ) | 返回对应于给定格式的结构的大小,返回占用多少字节的内存 |
1.3 格式化字符串
格式化字符串就是按照特定的方式来打包或解包,用于指定数据类型、控制字节顺序、大小和对齐方式的特殊字符。
端: 数据在存储器中存放顺序的顺序。
分度值,byte,即byte都是按照正常顺序,但是byte组装成的int时byte的顺序则不同。
| 大端 | 小端 |
|---|---|
| 较低的有效字节存放在较高的存储器地址中,较高的有效字节存放在较低的存储器地址 | 较高的有效字节存放在较高的存储器地址中,较低的有效字节存放在较低的存储器地址 |
格式字符串的第一个字符可用于指示打包数据的字节顺序,大小和对齐方式:
| 字符 | 字节顺序 | 尺寸 | 对准 |
|---|---|---|---|
@ |
本机 | 本机 | 本机 |
= |
本机 | 标准 | 没有 |
< |
小端 | 标准 | 没有 |
> |
大端 | 标准 | 没有 |
! |
网络(大端) | 标准 | 没有 |
格式化字符可以给定它们的类型。
“标准大小”列是指使用标准大小时打包值的大小,以字节为单位;也就是说,当格式字符串中的一个开始’<’,’>’,’!’或 ‘=’。使用本机大小时,打包值的大小取决于平台。
| 式 | C型 | Python类型 | 标准尺寸 |
|---|---|---|---|
x |
填充字节 | 没有价值 | |
c |
char |
长度为1的字符串 | 1个 |
b |
signed char |
整数 | 1个 |
B |
unsigned char |
整数 | 1个 |
? |
_Bool |
布尔 | 1个 |
h |
short |
整数 | 2 |
H |
unsigned short |
整数 | 2 |
i |
int |
整数 | 4 |
I |
unsigned int |
整数 | 4 |
l |
long |
整数 | 4 |
L |
unsigned long |
整数 | 4 |
q |
long long |
整数 | 8 |
Q |
unsigned long long |
整数 | 8 |
f |
float |
浮动 | 4 |
d |
double |
浮动 | 8 |
s |
char[] |
串 | |
p |
char[] |
串 | |
P |
void * |
整数 |
- _Bool在C99中定义,如果没有这个类型,则将这个类型视为char,一个字节;
- q和Q只适用于64位机器;
- 每个格式前可以有一个数字,表示这个类型的个数,如s格式表示一定长度的字符串,4s表示长度为4的字符串;4i表示四个int;
- P用来转换一个指针,其长度和计算机相关;
- f和d的长度和计算机相关;
1.4 例子
```python读取二进制文件
from tkinter import * import tkinter.filedialog import struct
创建应用程序的类
class App: def init(self,master):
##创建一个label控件self.label = Label(master)self.label.pack(anchor=W)##创建一个Button控件self.button = Button(master,text='Start',command=self.getBinaryData)self.button.pack(anchor = CENTER)def setBinaryData(self):##将数值数据100,200,300,400转换成integer类型的二进制数据self.bytes = struct.pack("i"*4, 100, 200, 300, 400)def getBinaryData(self):self.setBinaryData()##将integer类型的二进制数据转换为数值数据100,200,300,400values = struct.unpack("i"*4, self.bytes)self.label.config(text=str(values))
创建应用程序窗口
win = Tk() win.title(string = “平面数据库”)
创建应用程序类的实例变量
app = App(win)
开始窗口的事件循环
win.mainloop()
 <a name="doMjM"></a>## 二、SQLite数据库<a name="z459z"></a>### 2.1 介绍SQLite数据库是一款小型的嵌入式开源数据库软件,没有独立的维护进程,所有的维护都来自于程序本身,不需要作为独立的服务器允许,可以直接在本地允许。<br />它是遵守ACID的关联式数据库管理系统的,能够支持Windows/Linux/Unix等主流的操作系统,同时能够和很多程序语音相结合,eg:Tcl、C#、PHP、Java等,还有ODBC接口,与Mysql、PostgreSQL相比,处理速度更快。<br />SQLite引擎不是独立于程序之外的独立进程,而是连接到程序中成为它的一个主要部分。<br />主要的通信协议是在编程语言内直接通过API调用,在消耗总量、延迟事件和整体简单上均有积极的作用。<br />整个数据库(定义、表、索引和数据本身)都在宿主主机上,存储在一个单一的文件中。<br />在Python3中,SQLite已经被包装为标准库pySQLite,可以作为模块导入。<a name="l2bu6"></a>### 2.2 连接数据库为了使用sqlite3,必须首先创建一个表示数据库的连接对象```pythonimport sqlite3 #导入sqlite2模块conn = sqlite3.connect("E:\\pythonstduy\\shujuku\\test.db") #如果不存在,创建数据库test.db如果test.db存在,就直接打开,同时创建数据库连接对象conn
connect() 函数返回一个连接对象conn,这个对象是目前和数据库的连接对象,支持的方法:
| 方法 | 说明 |
|---|---|
| close() | 关闭连接。连接关闭后,连接对象和游标均不可用 |
| commit() | 提交事务,保存数据。如果不提交,则不保存数据,数据库中为上次调用commit()方法之后的数据。 ps:数据库需要支持事务,如果数据库不支持事务,这个方法不会起作用 |
| rollback() | 回滚挂起的事务,恢复到上次调用commit()方法后的数据状态 |
| cursor() | 返回连接的游标对象 |
2.3 使用游标查询数据库
创建数据库连接对象conn连接到数据库后,需要打开游标(cursor)。
通过Cursor执行SQL语句实现对数据库表的查询、插入、修改、删除等操作。
在sqlite3中,所有SQL语句的执行都要在游标对象的参与下完成,
Cursor对象的主要方法
| 方法 | 说明 |
|---|---|
| callproc(name [, params]) | 使用给的那个的名称和参数(可选)调用已命名的数据库 |
| execute(sql [,params]) | 执行一条SQL语句 |
| executemany(sql [,params]) | 执行多条SQL语句 对于所有给定参数执行同一条SQL语句,一般参数是一个序列 |
| fetchone() | 从结果中取出一条记录 |
| fetchmany([size]) | 从结果中取出多条记录 |
| fetchall() | 从结果中取出所有记录 |
| nextset() | 跳至下一跳可用的结果集 |
| scroll() | 游标滚动 |
| setinputsizes(sizes) | 为参数预先定义内存区域 |
| setoutputsizes(size [,col] | 为获取的大数据值设置缓冲区大小 |
| close() | 关闭游标,游标关闭后,游标将不可用 |
Cursor对象的属性
| 属性 | 说明 |
|---|---|
| description | 结果列描述的序列,只读 |
| rowcount | 结果中的行数,只读 |
| arraysize | fetchmany中返回的行数,默认为1 |
2.4 实例
####创建数据库并使用游标查询数据库import sqlite3 #导入sqlite3模块conn = sqlite3.connect("E:\\pythonstduy\\shujuku\\school.db") #连接数据库school.db,创建数据库连接对象cursor = conn.cursor() #打开游标print("数据库已经打开")#创建表cursor.execute('''CREATE TABLE STUDENT(ID int primary key not null,NAME text not null,Age int not null,Score int not null,Address char(50))''')print("创建表成功")##插入记录cursor.execute('''INSERT INTO STUDENT VALUES(1001,'炎',20,665,"山西太原")''')cursor.execute('''INSERT INTO STUDENT VALUES(1002,"桓",21,601,"浙江杭州")''')cursor.execute('''INSERT INTO STUDENT VALUES(1003,"彻",22,630,"陕西西安")''')cursor.execute('''INSERT INTO STUDENT VALUES(1004,"景",20,660,"陕西咸阳")''')print("插入数据完成")conn.commit() #提交当前事务,保存数据for row in cursor.execute('select * from STUDENT'): #查询表中数据print(row)conn.close() #关闭数据连接##结果数据库已经打开创建表成功插入数据完成(1001, '炎', 20, 665, '山西太原')(1002, '桓', 21, 601, '浙江杭州')(1003, '彻', 22, 630, '陕西西安')(1004, '景', 20, 660, '陕西咸阳')##使用fetchall() 等方法提取需要的结果import sqlite3,sysconn = sqlite3.connect("E:\\pythonstduy\\shujuku\\school.db") #连接数据库school.db,创建数据库连接对象curs = conn.cursor() #创建一个连接的游标curs.execute('''SElECT * FROM STUDENTWHERE ID = 1001''')names = [f[0] for f in curs.description]#curs.description是游标对象列描述的序列for raw in curs.fetchall():#从结果中读取全部的结果,读取所有的列名for pair in zip(names, raw):#将给定的 list 的每一个变成一个元组,用法为 zip(∗list),将列名和内容对应成一个元组对象print('%s: %s' % pair)##结果ID: 1001NAME: 炎Age: 20Score: 665Address: 山西太原
三、MySQL数据库
3.1 PyMySQL
Python为操作mysql数据库提供了标准库PyMySQL。
官网:https://pypi.org/project/PyMySQL/
官方文档:https://pymysql.readthedocs.io/en/latest/
下载:
3.2 连接MySQL数据库
首先需要安装mysql服务器软件
MySQL > = 5.5
MariaDB > = 5.5
然后需要创建空的数据库ffs
查询目前mysql数据库的版本
import pymysql#打开数据库连接 参数依次是[IP,用户名,密码,数据库名]db = pymysql.connect("localhost","root",'1054052026',"ffs")##使用cursor() 方法创建一个游标对象cursor = db.cursor()#使用execute() 方法执行SQL查询cursor.execute('''SELECT VERSION()''')##使用fetchone() 方法获取单条数据data = cursor.fetchone()#输出查询到的数据print("Database version : %s" % data)#关闭数据库连接db.close()##结果Database version : 10.4.12-MariaDB
3.3 创建数据表
import pymysql#打开数据库连接db = pymysql.connect("localhost","root",'1054052026',"ffs")#使用cursor()方法创建一个游标cursor = db.cursor()#创建数据表cursor.execute('''CREATE TABLE STUDENT(ID int primary key not null,NAME text not null,Age int not null,Score int not null,Address char(50))''')print("STUDENT表创建成功")#关闭数据库连接db.close()##结果STUDENT表创建成功
3.4 插入数据
import pymysql#打开数据库连接db = pymysql.connect("localhost","root",'1054052026',"ffs")#使用cursor()方法创建一个游标cursor = db.cursor()#SQL语句sql = "INSERT INTO STUDENT VALUES (1003,'彻',22,630,'陕西西安')"try:#执行插入语句cursor.execute(sql)#提交到数据库执行db.commit()except:#如果发生错误,回滚数据库db.rollback()#关闭数据库连接db.close()
3.5 查询数据
| 方法 | 说明 |
|---|---|
| fetchone() | 获取下一个查询结果集,结果集是一个对象 |
| fetchall() | 接收全部的返回结果行 |
| rowcount | 一个只读属性,返回执行execute() 方法后影响的行数 |
import pymysql#打开数据库连接db = pymysql.connect("localhost","root",'1054052026',"ffs")#使用cursor()方法创建一个游标cursor = db.cursor()#SQL语句sql = "select * from STUDENT where ID >'%d' "%(500)#执行SQL语句try:#执行插入语句cursor.execute(sql)#curs.description是游标对象列描述的序列names = [f[0] for f in cursor.description]#获取所有记录列表result = cursor.fetchall()for row in result:#给定的 list 的每一个变成一个元组,用法为 zip(∗list),将列名和内容对应成一个元组对象for pair in zip(names,row):print('%s: %s' % pair)except:print("错误:无法查询数据")##关闭数据库连接db.close()##结果ID: 1003NAME: 彻Age: 22Score: 630Address: 陕西西安
3.6 更新数据
使用UPDATE语句可以更新数据库记录
import pymysql#打开数据库连接db = pymysql.connect("localhost","root",'1054052026',"ffs")#使用cursor()方法创建一个游标cursor = db.cursor()#sql语句sql = "UPDATE STUDENT SET ID = ID +10"#执行sql语句try:#执行更新数据sql语句cursor.execute(sql)#提交到数据库执行db.commit()except:#发生错误,回滚数据库db.rollback()#关闭数据库连接db.close()
3.7 删除数据
使用DELETE语句删除数据表中的数据
drop database 数据库名 —删除数据库的
drop table 表名–删除表的
delete from 表名 where 条件 —删除数据的
import pymysql#打开数据库连接db = pymysql.connect("localhost","root",'1054052026',"ffs")#使用cursor()方法创建一个游标cursor = db.cursor()#sql语句sql = " DELETE FROM STUDENT WHERE ID >'%d' "%(1002)#执行sql语句try:#执行删除数据sql语句cursor.execute(sql)#提交到数据库执行db.commit()print("删除成功")except:#发生错误,回滚数据库print("错误")db.rollback()#关闭数据库连接db.close()##结果删除成功
四、异常
| 异常 | 说明 |
|---|---|
| Warning | 当有严重警告的时候触发 eg:插入数据时被截断等,必须是StandardError的子类 |
| Error | 警告以外所有其他错误类,必须是StandardError的子类 |
| InterfaceError | 当有数据库接口模块本身的错误(不是数据库的错误)发生时触发。 必须时Error的子类 |
| DatabaseError | 与数据库有关的错误发生时触发,必须是Error的子类 |
| DataError | 当有数据处理并发送错误的时候触发,eg:除零错误、数据超范围等。 必须是DatabaseError的错误 |
| OperationalError | 指非用户控制的,而是操作数据库时发生的错误,eg:连接意外断开、数据库名未找到、事务处理失败、内存分配错误。 必须是DatabaseError的错误 |
| IntegrityDrrot | 完整性相关的错误,eg:外键检查失败等。 必须是DatabaseError的错误 |
| InternalError | 数据库的内部错误,eg:游标(curcor)失败、事务同步失败等。 必须是DatabaseError的错误 |
| ProgrammingError | 程序错误,eg:数据表(table)没找到或已存在、SQL语句语法错误、参数数量错误等。 必须是DatabaseError的错误 |
