1 Python数据库编程基础知识
- 带有数据库的应用程序系统一般采用的是C/S(Client/Server,客户端/服务器)模式。
- 安装了数据库服务软件(例如MySQL)的联网计算机,称为数据库服务器,它为网络中其他计算机提供提供数据库服务。
- 我们可以在客户端计算机上用Python编写程序,通过网络访问数据库服务器上面的数据库,并进行数据操作。
1.1 Python DB API

当应用程序想切换不同的的数据库时,由于程序接口的混乱所带来的代价是非常大的。为此,Python 官方规范访问数据库的接口,防止在使用不同数据库时造成的问题。这个官方规范的接口叫做 Python DB API(https://www.python.org/dev/peps/pep-0249) 。有了这接口带来的好处不言而喻,大大方便数据库的访问,开发只需要学习了API,就可以以少量的修改为代价进行不同数据库的切换。

1.2 Python DB API包含的内容
API中主要的模块如下:
Connection 连接,用于客户端连接数据库服务器
Cursor 游标,用于客户端程序向数据库服务发送SQL查询请求和接收查询结果
1.3 Python DB API访问数据库流程

2 PyMySQL库简介与安装
2.1 pymsql库简介
PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库。
2.2 pymysql库安装
可以使用以下命令安装最新版的 PyMySQL:
$ pip3 install PyMySQL
如果系统不支持 pip 命令,可以使用以下方式安装:
使用 git 命令下载安装包安装(也可以手动下载):
$ git clone https://github.com/PyMySQL/PyMySQL$ cd PyMySQL/$ python3 setup.py install
3 使用pymysql操作数据库
3.1 pymysql数据库编程前的准备工作
在使用python进行数据库编程之前需要做好以下准备工作:
- 在开发程序的计算机上安装了pymysql库
- 掌握数据库服务器的IP地址(域名,DNS Domain Name System 域名系统)、端口号、用户名、数据库名、用户权限
在下面的练习中,我们将使用如下数据库服务和数据库
- 数据库服务器IP : 192.168.179.231
- 数据库服务端口:3306
- 用户名:test
- 密码:123456
- 数据库名:test
- 用户权限:select
3.2 pymsql的connection对象
生成对象的方法:pymysql.connect,这个方法会返回一个数据库的连接对象(connection),connect方法参数如下:
connection 对象支持的方法:
```python
import pymysql
conn=pymysql.connect( host=”192.168.179.231”, user=”test”, password=”123456”, database=”test”, charset=”utf8” ) cursors=conn.cursor() cursors.close() conn.close()
if name == “main“: print(conn) print(cursors)
<a name="CVbaB"></a>## 3.3 pymsql的游标对象cursor游标对象:用于执行查询和获取结果<br />cursor对象支持的方法:<br /><br />其中execute方法:执行SQL将结果从数据库获取到客户端的过程如下:<br /><br />fetch*()方法的过程如下:<br /><br />**使用pymysql编写数据库访问程序的基本过程**<br />1.使用connnect方法创建数据库连接,生成连接对象<br />2.使用连接对象的cursor方法,创建游标对象<br />3.使用游标对象的cursor的execute方法,将SQL查询提交给数据库服务器执行,将结果存放在程序缓冲区<br />4.使用cursor的fetch方法,从缓冲区获取数据库(fetchone,fetchmany,fetchall)<br />5.关闭游标,关闭连接。<br />[testconn.py](https://www.yuque.com/attachments/yuque/0/2022/txt/28265088/1652323974185-c85eb21f-3796-41b8-9bcd-742fc145af69.txt?_lake_card=%7B%22src%22%3A%22https%3A%2F%2Fwww.yuque.com%2Fattachments%2Fyuque%2F0%2F2022%2Ftxt%2F28265088%2F1652323974185-c85eb21f-3796-41b8-9bcd-742fc145af69.txt%22%2C%22name%22%3A%22testconn.py%22%2C%22size%22%3A967%2C%22type%22%3A%22text%2Fplain%22%2C%22ext%22%3A%22txt%22%2C%22source%22%3A%22%22%2C%22status%22%3A%22done%22%2C%22mode%22%3A%22title%22%2C%22download%22%3Atrue%2C%22taskId%22%3A%22u6fb7d653-76eb-4866-8e00-70d01e9b89f%22%2C%22taskType%22%3A%22upload%22%2C%22id%22%3A%22u6d2bcbe5%22%2C%22card%22%3A%22file%22%7D)```pythonimport pymysqlconn=pymysql.connect(host="192.168.179.231",user="test",password="123456",database="test",charset="utf8")cursors=conn.cursor()cursors.execute("select * from users")data=cursors.fetchall()cursors.close()conn.close()if __name__ == "__main__":print(conn)print(cursors)for item in data:print(item)
登录验证的测试程序
import pymysqlimport wx#导入wxPython包class MainFrame(wx.Frame):#定义MainFrame类(代表程序的主窗体),它是wx.Frame类的子类def __init__(self):#主窗体的构造方法super().__init__(parent=None,id=-1,title="程序主窗体",size=(400,300))#调用wx.Frame类的构造方法来创建程序主窗体self.panel=wx.Panel(parent=self)#定义了panel对象,他是个wx.Panel类对象,代表一个面板self.title=wx.StaticText(parent=self.panel,label="请输入用户名和密码",pos=(140,20))#定义一个wx.StaticText控件类对象,这是一个文本标签类self.userLabel=wx.StaticText(self.panel,label="用户名:",pos=(50,50))self.userText=wx.TextCtrl(self.panel,pos=(100,50),size=(235,25),style=wx.TE_LEFT)#定义一个wx.TextCtrl控件对象,这是一个文本输入框,其中,pos代表位置,size代表大小,style代表是文本框的风格self.passLabel=wx.StaticText(self.panel,label="密 码:",pos=(50,90))self.passText=wx.TextCtrl(self.panel,pos=(100,90),size=(235,25),style=wx.TE_PASSWORD)self.btnOK=wx.Button(self.panel,label="确 定",pos=(105,130))#定义了按钮类wx.Button的对象self.btnCancel=wx.Button(self.panel,label="取 消",pos=(195,130))self.Bind(wx.EVT_BUTTON,self.OnClickOK,self.btnOK)#绑定btnOK的按钮点击事件的事件事件处理方法是OnClickOKself.Bind(wx.EVT_BUTTON,self.OnClickCancel,self.btnCancel)def validate(self,user,passwd):conn = pymysql.connect(host="192.168.179.231",user="test",password="123456",database="test",charset="utf8")cursors = conn.cursor()sqlStatement='select name,passwd from users where name="'+user+'" and passwd="'+passwd+'"'# print(sqlStatement)cursors.execute(sqlStatement)data = cursors.fetchone()# print(data)if data:return Trueelse:return Falsedef OnClickOK(self,event):#定义MainFrame类的方法OnClickOK,用来进行btnOk(“确定”)被点击之后事件处理#user="Tom"#passwd="123456"#这是要验证的用户名和密码userName=self.userText.GetValue()#从userText中取出输入的用户名,使用TextCtrl对象的GetValue()方法取出输入的内容userPass=self.passText.GetValue()#从passText中取出输入的密码message = ""if userName == "" or userPass == "":message = "用户名或密码不能为空"elif self.validate(userName,userPass) :message = "用户"+userName+"登录成功"else:message = "用户名或者密码不匹配"wx.MessageBox(message,"登录提示")#创建一个MessageBox对象,显示提示信息def OnClickCancel(self,event):#OnClickCancel定义Cancel按钮点击后的事件处理程序self.userText.SetValue("")#将userText文本框清空self.passText.SetValue("")if __name__ == "__main__" :app=wx.App()#定义一个wx.App类的对象appmainFrame=MainFrame()mainFrame.Show()app.MainLoop()#启动app的事件循环,等待捕获用户在GUI界面上的操作(即控件事件),然后进入事件响应程序,执行事件响应程序#执行完成以后,回到事件循环。直至捕获到退出事件发生,才结束应用程序。# import pymysql# conn = pymysql.connect(host="192.168.179.231",user="test",password="123456",database="test", charset="utf8")# cursors = conn.cursor()# user="mike"# passwd="123456"# sqlStatement='select name,passwd from users where name="'+user+'" and passwd="'+passwd+'"'# print(sqlStatement)# cursors.execute(sqlStatement)# data = cursors.fetchone()# print(data)
3.4 数据库的更新操作
数据库的更新操作涉及insert、update、delete
import pymysqluname=input("请输入用户名:")upasswd=input("请输入用户密码:")conn=pymysql.connect(host="192.168.179.231",port=3306,user="test",password="123456",database="test",)cursor=conn.cursor()sqlst='insert into users(name,passwd) values("{}","{}")'.format(uname,upasswd)print("sqlst=",sqlst)try:cursor.execute(sqlst)conn.commit()#提交查询# for item in cursor.fetchall():# print(item)except:conn.rollback()#对数据库服务器进行事务回滚print("数据库操作错误!")else:print("数据库查询操作无误时,执行的代码.")finally:print("结束数据库访问操作,关闭连接.")cursor.close()conn.close()
import pymysql#导入pymysql包conn=pymysql.connect(host="192.168.179.231",user="test",password="123456",database="test")cursor=conn.cursor()sqlst='update users set passwd="Abc#123" where name="mike"'cursor.execute(sqlst)conn.commit()#conn.commit()方法,将查询提交给数据库服务器cursor.close()conn.close()
employees(员工)数据库是mysql官方提供的一个用于学习和测试的样例数据库
以employees表为例
emp_no 员工工号
first_name 员工名字
last_name 员工姓氏
gender 性别(M(Male) 代表 男性,F(Femal) 代表女性)
brith_date 生日
hire_date 雇佣日期
getEmployeesInfor.pytestemployees.py
findEmployee.py getEmployeesDetail.py
4 错误处理
DB API中定义了一些数据库操作的错误及异常,下表列出了这些错误和异常:
| 异常 | 描述 |
|---|---|
| Warning | 当有严重警告时触发,例如插入数据是被截断等等。必须是 StandardError 的子类。 |
| Error | 警告以外所有其他错误类。必须是 StandardError 的子类。 |
| InterfaceError | 当有数据库接口模块本身的错误(而不是数据库的错误)发生时触发。 必须是Error的子类。 |
| DatabaseError | 和数据库有关的错误发生时触发。 必须是Error的子类。 |
| DataError | 当有数据处理时的错误发生时触发,例如:除零错误,数据超范围等等。 必须是DatabaseError的子类。 |
| OperationalError | 指非用户控制的,而是操作数据库时发生的错误。例如:连接意外断开、 数据库名未找到、事务处理失败、内存分配错误等等操作数据库是发生的错误。 必须是DatabaseError的子类。 |
| IntegrityError | 完整性相关的错误,例如外键检查失败等。必须是DatabaseError子类。 |
| InternalError | 数据库的内部错误,例如游标(cursor)失效了、事务同步失败等等。 必须是DatabaseError子类。 |
| ProgrammingError | 程序错误,例如数据表(table)没找到或已存在、SQL语句语法错误、 参数数量错误等等。必须是DatabaseError的子类。 |
| NotSupportedError | 不支持错误,指使用了数据库不支持的函数或API等。例如在连接对象上 使用.rollback()函数,然而数据库并不支持事务或者事务已关闭。 必须是DatabaseError的子类。 |


