1 Python数据库编程基础知识

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

1.1 Python DB API

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

image.png

1.2 Python DB API包含的内容

API中主要的模块如下:
Connection 连接,用于客户端连接数据库服务器
Cursor 游标,用于客户端程序向数据库服务发送SQL查询请求和接收查询结果

image.png
各模块的作用可以用一张图表示如下:
image.png

1.3 Python DB API访问数据库流程

image.png

2 PyMySQL库简介与安装

2.1 pymsql库简介

PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库。

2.2 pymysql库安装

可以使用以下命令安装最新版的 PyMySQL:

  1. $ pip3 install PyMySQL

如果系统不支持 pip 命令,可以使用以下方式安装:
使用 git 命令下载安装包安装(也可以手动下载):

  1. $ git clone https://github.com/PyMySQL/PyMySQL
  2. $ cd PyMySQL/
  3. $ python3 setup.py install

3 使用pymysql操作数据库

3.1 pymysql数据库编程前的准备工作

在使用python进行数据库编程之前需要做好以下准备工作:

  1. 在开发程序的计算机上安装了pymysql库
  2. 掌握数据库服务器的IP地址(域名,DNS Domain Name System 域名系统)、端口号、用户名、数据库名、用户权限

在下面的练习中,我们将使用如下数据库服务和数据库

  • 数据库服务器IP : 192.168.179.231
  • 数据库服务端口:3306
  • 用户名:test
  • 密码:123456
  • 数据库名:test
  • 用户权限:select

    3.2 pymsql的connection对象

    生成对象的方法:pymysql.connect,这个方法会返回一个数据库的连接对象(connection),connect方法参数如下:
    image.png
    connection 对象支持的方法:
    image.png ```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)

  1. <a name="CVbaB"></a>
  2. ## 3.3 pymsql的游标对象cursor
  3. 游标对象:用于执行查询和获取结果<br />cursor对象支持的方法:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/28265088/1652278303556-bc228284-ecec-41f7-ad2d-2e02b71b45ae.png#clientId=u342159cd-a153-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u212ded31&margin=%5Bobject%20Object%5D&name=image.png&originHeight=189&originWidth=550&originalType=url&ratio=1&rotation=0&showTitle=false&size=99527&status=done&style=none&taskId=ue32cd5b6-39f0-4224-becb-4a852aee24b&title=)<br />其中execute方法:执行SQL将结果从数据库获取到客户端的过程如下:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/28265088/1652278303488-424d50e3-3f96-4c5a-a2bc-3ae289c5adc4.png#clientId=u342159cd-a153-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u52d5556a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=202&originWidth=580&originalType=url&ratio=1&rotation=0&showTitle=false&size=52923&status=done&style=none&taskId=u2ce08cf6-c712-4219-b08c-70654fe6773&title=)<br />fetch*()方法的过程如下:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/28265088/1652278303553-0bb9edda-3a5d-4c91-a161-22a5d6f5cbbf.png#clientId=u342159cd-a153-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=230&id=u58c79898&margin=%5Bobject%20Object%5D&name=image.png&originHeight=294&originWidth=727&originalType=url&ratio=1&rotation=0&showTitle=false&size=114555&status=done&style=none&taskId=ud3925749-edda-4611-a51a-34117255ec1&title=&width=569)<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)
  4. ```python
  5. import pymysql
  6. conn=pymysql.connect(
  7. host="192.168.179.231",
  8. user="test",
  9. password="123456",
  10. database="test",
  11. charset="utf8"
  12. )
  13. cursors=conn.cursor()
  14. cursors.execute("select * from users")
  15. data=cursors.fetchall()
  16. cursors.close()
  17. conn.close()
  18. if __name__ == "__main__":
  19. print(conn)
  20. print(cursors)
  21. for item in data:
  22. print(item)

登录验证的测试程序
python数据库编程 - 图8

testlogin.py
image.png
login.py

  1. import pymysql
  2. import wx
  3. #导入wxPython包
  4. class MainFrame(wx.Frame):
  5. #定义MainFrame类(代表程序的主窗体),它是wx.Frame类的子类
  6. def __init__(self):
  7. #主窗体的构造方法
  8. super().__init__(parent=None,id=-1,title="程序主窗体",size=(400,300))
  9. #调用wx.Frame类的构造方法来创建程序主窗体
  10. self.panel=wx.Panel(parent=self)
  11. #定义了panel对象,他是个wx.Panel类对象,代表一个面板
  12. self.title=wx.StaticText(parent=self.panel,label="请输入用户名和密码",pos=(140,20))
  13. #定义一个wx.StaticText控件类对象,这是一个文本标签类
  14. self.userLabel=wx.StaticText(self.panel,label="用户名:",pos=(50,50))
  15. self.userText=wx.TextCtrl(self.panel,pos=(100,50),size=(235,25),style=wx.TE_LEFT)
  16. #定义一个wx.TextCtrl控件对象,这是一个文本输入框,其中,pos代表位置,size代表大小,style代表是文本框的风格
  17. self.passLabel=wx.StaticText(self.panel,label="密 码:",pos=(50,90))
  18. self.passText=wx.TextCtrl(self.panel,pos=(100,90),size=(235,25),style=wx.TE_PASSWORD)
  19. self.btnOK=wx.Button(self.panel,label="确 定",pos=(105,130))
  20. #定义了按钮类wx.Button的对象
  21. self.btnCancel=wx.Button(self.panel,label="取 消",pos=(195,130))
  22. self.Bind(wx.EVT_BUTTON,self.OnClickOK,self.btnOK)
  23. #绑定btnOK的按钮点击事件的事件事件处理方法是OnClickOK
  24. self.Bind(wx.EVT_BUTTON,self.OnClickCancel,self.btnCancel)
  25. def validate(self,user,passwd):
  26. conn = pymysql.connect(
  27. host="192.168.179.231",
  28. user="test",password="123456",
  29. database="test",
  30. charset="utf8")
  31. cursors = conn.cursor()
  32. sqlStatement='select name,passwd from users where name="'+user+'" and passwd="'+passwd+'"'
  33. # print(sqlStatement)
  34. cursors.execute(sqlStatement)
  35. data = cursors.fetchone()
  36. # print(data)
  37. if data:
  38. return True
  39. else:
  40. return False
  41. def OnClickOK(self,event):
  42. #定义MainFrame类的方法OnClickOK,用来进行btnOk(“确定”)被点击之后事件处理
  43. #user="Tom"
  44. #passwd="123456"
  45. #这是要验证的用户名和密码
  46. userName=self.userText.GetValue()
  47. #从userText中取出输入的用户名,使用TextCtrl对象的GetValue()方法取出输入的内容
  48. userPass=self.passText.GetValue()
  49. #从passText中取出输入的密码
  50. message = ""
  51. if userName == "" or userPass == "":
  52. message = "用户名或密码不能为空"
  53. elif self.validate(userName,userPass) :
  54. message = "用户"+userName+"登录成功"
  55. else:
  56. message = "用户名或者密码不匹配"
  57. wx.MessageBox(message,"登录提示")
  58. #创建一个MessageBox对象,显示提示信息
  59. def OnClickCancel(self,event):
  60. #OnClickCancel定义Cancel按钮点击后的事件处理程序
  61. self.userText.SetValue("")
  62. #将userText文本框清空
  63. self.passText.SetValue("")
  64. if __name__ == "__main__" :
  65. app=wx.App()
  66. #定义一个wx.App类的对象app
  67. mainFrame=MainFrame()
  68. mainFrame.Show()
  69. app.MainLoop()
  70. #启动app的事件循环,等待捕获用户在GUI界面上的操作(即控件事件),然后进入事件响应程序,执行事件响应程序
  71. #执行完成以后,回到事件循环。直至捕获到退出事件发生,才结束应用程序。
  72. # import pymysql
  73. # conn = pymysql.connect(host="192.168.179.231",user="test",password="123456",database="test", charset="utf8")
  74. # cursors = conn.cursor()
  75. # user="mike"
  76. # passwd="123456"
  77. # sqlStatement='select name,passwd from users where name="'+user+'" and passwd="'+passwd+'"'
  78. # print(sqlStatement)
  79. # cursors.execute(sqlStatement)
  80. # data = cursors.fetchone()
  81. # print(data)

3.4 数据库的更新操作

数据库的更新操作涉及insert、update、delete

  1. import pymysql
  2. uname=input("请输入用户名:")
  3. upasswd=input("请输入用户密码:")
  4. conn=pymysql.connect(
  5. host="192.168.179.231",
  6. port=3306,
  7. user="test",
  8. password="123456",
  9. database="test",
  10. )
  11. cursor=conn.cursor()
  12. sqlst='insert into users(name,passwd) values("{}","{}")'.format(uname,upasswd)
  13. print("sqlst=",sqlst)
  14. try:
  15. cursor.execute(sqlst)
  16. conn.commit()
  17. #提交查询
  18. # for item in cursor.fetchall():
  19. # print(item)
  20. except:
  21. conn.rollback()
  22. #对数据库服务器进行事务回滚
  23. print("数据库操作错误!")
  24. else:
  25. print("数据库查询操作无误时,执行的代码.")
  26. finally:
  27. print("结束数据库访问操作,关闭连接.")
  28. cursor.close()
  29. conn.close()
  1. import pymysql
  2. #导入pymysql包
  3. conn=pymysql.connect(
  4. host="192.168.179.231",
  5. user="test",
  6. password="123456",
  7. database="test"
  8. )
  9. cursor=conn.cursor()
  10. sqlst='update users set passwd="Abc#123" where name="mike"'
  11. cursor.execute(sqlst)
  12. conn.commit()
  13. #conn.commit()方法,将查询提交给数据库服务器
  14. cursor.close()
  15. conn.close()

employees(员工)数据库是mysql官方提供的一个用于学习和测试的样例数据库
image.png
以employees表为例
emp_no 员工工号
first_name 员工名字
last_name 员工姓氏
gender 性别(M(Male) 代表 男性,F(Femal) 代表女性)
brith_date 生日
hire_date 雇佣日期

python数据库编程 - 图11

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的子类。