Python学习笔记8:数据库

Python学习笔记8:数据库

安装MySQL python/connector

官方下载页面为:https://dev.mysql.com/downloads/

选择Connector/Python

选择操作系统为Source Code,Os Version为Platform Independent

这样的选择是为了使用纯Python编写的MySQL驱动,效率可能是比不上Windows安装包,但学习是足够了。

windows系统选择zip,Linux系统选择gz。

这里选择No thanks, just start my download.即可。

解压压缩包:

那个setup.py即是安装程序。

用管理员权限运行CMD,然后执行安装命令

python3 setup.py install

安装失败,这是因为我的Python是用Windows store安装的,在WindowsApps这个目录下,是受访问限制的。

我尝试了修改访问权限,可是依然不行,居然还把环境变量给搞乱掉了,命令行下都不能正常启动python了,也是无比操蛋。

我选择放弃,删除windows store版本的Python,在Python官网下了个安装包后自行安装,这里最好是直接安装到非系统目录,windows的权限管理实在太操蛋了,惹不起。

重启后可以正常使用python,就是不能使用python3命令,可能是缺乏软连接之类的,不过不影响使用。

重新尝试安装MySQL驱动,可以正常安装。

因为重新安装了Python的缘故,那些第三方模块都没了,pip的版本也不是最新的,顺手重新更新一波。

设置MySQL数据库

我这里使用的MySQL数据库是XAMPP附带的,打开XAMPP确认MySQL服务是否启用:

想了解如何下载和使用XAMPP的可以阅读PHP开发环境(XAMPP+XDebug+VSCode)搭建

现在去设置一个配套的数据库,我常用的MySQL管理工具是SQLyog。

安装包已上传到百度盘

链接:https://pan.baidu.com/s/1SyfrXM8dpOSZ2iM-tIGufA
提取码:lqm5
复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V1的分享

安装好后填入注册信息:

名称:ddooo;
证书秘钥:8d8120df-a5c3-4989-8f47-5afc79c56e7c;

第一次启动的时候创建一个对本地MySQL数据库的连接:

XAMPP的附带MySQL是没设置密码的,所以这里密码保持为空。

连接上后就可以创建自己的数据库,我这里是创建了一个数据库myweb

我们还需要创建一张日志表,稍后会用这个表来记录我们之前web应用中的日志。

使用Python连接数据库

我们写个简单的程序test.py验证一下数据库连接是否正常。

import mysql.connector
dbconfig = {"host": "127.0.0.1", "user": "root",
            "password": "", "database": "myweb"}
conn = mysql.connector.connect(**dbconfig)
cursor = conn.cursor()
_SQL = """SHOW TABLES"""
cursor.execute(_SQL)
results = cursor.fetchall()
print(results)
cursor.close()
conn.close()

输出

[('log',)]

数据库连接中有以下几个要点:

  1. import mysql.connector为导入Python自带的DB-API,这是一个Python官方制作的对于数据库的抽象层,可以屏蔽底层数据库差异,而使得程序对数据库的使用更加灵活。

  2. dbconfig是数据库信息字典,用于连接数据库。

  3. mysql.connector.connect(**dbconfig)将返回一个数据库连接句柄,其中**dbconfig是以字典的方式传入参数。

  4. conn.cursor()是获取一个游标,具体的SQL操作将使用这个游标来实现。

  5. _SQL = """SHOW TABLES"""这是构建了一个SQL语句,在Python中通常使用docstring的方式来构建,因为这样可以让SQL语句跨多行,更便于阅读。

  6. cursor.fetchall()将返回所有查询结果,相应的还有cursor.fetchone()等。

  7. cursor.close()为关闭游标,如果成功,会返回True

  8. conn.close()为关闭数据库连接。

    对于一个商用频繁访问数据库连接的应用,可能需要使用单例来保持一个有限时间内的长连接,这样效率更高,但对于学习用的小程序,及时关闭数据库连接对资源利用来说更有效。

一切正常,我们现在可以改造我们前几篇笔记中的web应用了,用数据库读写的方式替代文件操作。

用数据库改进web应用

这里使用的web应用示例沿用之前的系列笔记,如果没有阅读过的,请阅读:

本篇笔记的web应用完整代码见文章末尾。

我们先创建一个数据库类mydb.py用于统一管理数据库操作:

import mysql.connector


class MyDB():
    def __init__(self):
        self.dbconfig = {"host": "127.0.0.1", "user": "root",
                         "password": "", "database": "myweb"}

    def connect(self):
        self.dbConnect = mysql.connector.connect(**self.dbconfig)
        self.cursor = self.dbConnect.cursor()

    def close(self):
        self.cursor.close()
        self.dbConnect.close()

    def executeSQL(self, _SQL: str, params: tuple) -> list:
        """执行SQL"""
        self.connect()
        self.cursor.execute(_SQL, params)
        results = self.cursor.fetchall()
        self.dbConnect.commit()
        self.close()
        return results

需要重点说明的是,我们在executeSQL方法中加入了self.dbConnect.commit(),这是为了在插入或更新操作后马上提交数据库以使变更立即生效,否则数据库将依照自己的优化推迟操作,我们有可能在提交插入日志后,在数据库中看不到新增的数据。当然这个提交操作也可以放在close()方法中,但那样在这个例子中是没问题的,但在长连接的场景下会同样出现之前的问题。

然后修改index.py中的日志写入部分,将文件读写替换为数据库:

def writeLog(logInfo: dict) -> None:
    _SQL = '''INSERT INTO LOG (phrase,letters,ip,browser_string,results)
            VALUES (%s,%s,%s,%s,%s)'''
    params = (logInfo['formData']['phrase'], logInfo['formData']
              ['letters'], logInfo['userIp'], logInfo['userAgent'], logInfo['results'])
    db = MyDB()
    db.executeSQL(_SQL, params)

在这里我们使用了DB-API在执行SQL时候对字符占位符的支持,分离了SQL和参数,这样可以避免字符出啊拼接带来的代码可读性降低。

现在用浏览器测试以下这个web应用,通过和之前博文中一样的操作,然后使用SQLyog查看数据库:

可以看到数据库中有相应数据了。

现在日志写入已经改好了,还需要修改日志读出的部分:

这里提供一个Python下web开发的小技巧:

因为在python的task框架下,所有打印行为都会直接输出到运行框架的cmd命令界面,而且显示并不友好,也显示的不完整,此时调试的时候我们可以借助前边笔记说的文件读写来观察变量内容,比如:

    # with open(file='myweb.log', mode='a') as fopen:
    #     print(results, file=fopen)
def getLog() -> list:
    lines = []
    db = MyDB()
    _SQL = '''SELECT * FROM LOG'''
    results = db.executeSQL(_SQL, tuple())
    for logInfo in results:
        lines.append([logInfo[4],logInfo[3],logInfo[1],logInfo[2],logInfo[5]])
    return lines

当然这里有个隐患,我们的查询顺序依赖于数据库表中的字段顺序,如果表结构发生改变这里可能会有问题,正确的做法是应该指明字段。

现在我们的日志中是把用户表单数据拆分开的,所以html模板也应该修改:

        <th>用户输入字符串</th>
        <th>检索字符串</th>

我们再访问以下日志页面:

显示的内容已经是来自数据库的了。

最后附上web应用的完整代码:

链接:https://pan.baidu.com/s/1XF9gbC1iEl_JCsZIta5rwA
提取码:mx0f
复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V1的分享

posted @ 2021-03-15 16:34  魔芋红茶  阅读(118)  评论(0编辑  收藏  举报