Python3 初学实践案例(8)使用 sqlite3 数据库存储生成的密码,prettytable 的使用

来源:互联网 发布:视频网络传输 编辑:程序博客网 时间:2024/04/29 07:48

Python3 初学实践案例(8)使用 sqlite3 数据库存储生成的密码,prettytable 的使用

在前面我用 python 脚本实现的 cli 版本的密码生成与管理工具中,我使用文本文件来存储我们的生成的密码。详情见:http://blog.csdn.net/fungleo/article/details/78842597

这样做我感觉还是有一些欠妥。因为这样查看的时候,必须使用系统命令,或者其他 GUI 工具进行查看。如果我要用 python 来处理和分析这个文本文件,无疑工作量是巨大的。

因此,我希望用数据库来存储我们生成的密码,然后用 sql 语句来进行查询,顺便写一个查询工具,这样就可以很方便的使用了。

在数据库的选型上,我决定使用单文件数据库 sqlite 。因为这样我们不需要安装一个数据库服务,并且可以随时复制走。

再说,就一个表就可以搞定的事情,搞个大型数据库也确实有点脱裤子放屁的感觉。

本文是 cli 密码生成管理工具的衍生文章。

开始实战

由于前面我们已经完成了密码生成工具的主体逻辑代码,这边只是将原来使用文本文件存储密码修改为数据库存储,所以,我不想大幅修改原有的文件。因此我新创建了一个 db.py 文件,来专门写相应的代码。

全部代码如下:

#!/usr/bin/env python3# -*- coding: UTF-8 -*-import sqlite3import reimport sysfrom prettytable import PrettyTableDB_PATH = sys.path[0] + '/passwd.db'def checkDB(db):    db.execute('''SELECT name FROM sqlite_master                WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'                ORDER BY 1''')    o = db.fetchall()    if len(o) == 0 or not bool(re.search(r'(\'passwd\',)',str(o))):        db.execute('''CREATE TABLE passwd (            id integer primary key autoincrement,            name varchar(255),            password varchar(255),            time timestamp default current_timestamp        )''')def insertDb(name,passwd):    conn = sqlite3.connect(DB_PATH)    c = conn.cursor()    checkDB(c)    c.execute("INSERT INTO passwd (name,password) VALUES ('" + name + "', '" + passwd + "')");    conn.commit()    conn.close()def selectDb(pid,name):    conn = sqlite3.connect(DB_PATH)    c = conn.cursor()    checkDB(c)    select = "SELECT * from passwd "    if name:        select += ('where name LIKE \'%' + name + '%\'')    if pid:        select += ('where id = \'' + str(pid) + '\'')    select += 'ORDER BY id DESC'    res = list(c.execute(select))    if len(res) == 0:        print('Info: record is empty')    else:        x = PrettyTable(['id','name','password','time'])        x.align['name'] = 'l'        x.padding_width = 1        for row in res:            x.add_row(list(row))        print(x)    conn.close()def deleteDb(pid):    conn = sqlite3.connect(DB_PATH)    c = conn.cursor()    checkDB(c)    c.execute('DELETE from passwd where id=' + str(pid) )    conn.commit()    o = conn.total_changes    if o == 0:        print('Failure: the password was not found')    if o == 1:        print('Success: ID ' + str(pid) + ' password has been deleted')    conn.close()

代码解析

确定数据库路径

我们的脚本写好后,我们可以在系统的任何地方运行这个脚本。因此,数据库路径必须使用绝对路径,否则存在哪里就不太清楚了。

我希望文件存储在和 db.py 文件的同级目录下,因此,我需要先获取到 db.py 这个文件所在的目录。我们使用 sys 库的基本功能来实现,代码如下:

import sysDB_PATH = sys.path[0] + '/passwd.db'

其中 sys.path[0] 就是获取文件存在的绝对路径,后面加上数据库文件名。然后存一个常量,我们就可以在下面的函数中使用数据库位置常量来调用数据库了。

sqlite 数据库的连接

首先,我们需要引入库,然后创建连接,连接打开后,我们执行我们希望操作的 sql 语句,然后再关闭连接,就完成了我们希望的工作了。

import sqlite3conn = sqlite3.connect(DB_PATH)c = conn.cursor()c.execute("__这里是一条SQL语句__");conn.commit()conn.close()

如上,基本就是一条 sql 语句的执行全过程了。当然,我们可以在一个连接内操作多条 SQL 语句,但是就我们的这个工具来说,一般都是一条一条的执行,需要执行的时候创建连接,连接好了之后,我们执行代码,然后提交,然后关闭。

如果数据库不存在,就会创建一个数据库文件,这个是个自动的机制,我们就不用管了。

在数据库中创建表

一个新创建的数据库当中是没有任何表的。我们不能要求我们的用户自己去搞好一个表再来使用。因此,当数据库不存在,在第一次链接的时候会自动创建这个数据库,但是这个数据库中是没有任何表的,所以,我们需要检查数据库中有没有表,如果有表,那么有没有我们使用的这个表,如果不符合条件,我们则需要创建一个表,并且这个表的结构要符合我们的设计。

整体代码如下:

import redef checkDB(db):    db.execute('''SELECT name FROM sqlite_master                WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'                ORDER BY 1''')    o = db.fetchall()    if len(o) == 0 or not bool(re.search(r'(\'passwd\',)',str(o))):        db.execute('''CREATE TABLE passwd (            id integer primary key autoincrement,            name varchar(255),            password varchar(255),            time timestamp default current_timestamp        )''')

如上,我们这个函数的作用就是检查状况,如果需要创建一个表,就直接创建。那么,在我们需要检查的地方,使用这个函数就可以检查了,如下代码:

def insertDb(name,passwd):    conn = sqlite3.connect(DB_PATH)    c = conn.cursor()    # 就是这里,我先检查了一下。    checkDB(c)    c.execute("INSERT INTO passwd (name,password) VALUES ('" + name + "', '" + passwd + "')");    conn.commit()    conn.close()

上面我使用了正则来检查数据库中是否存在我们需要的 passwd 表,所以我们需要引入正则库。

优雅的在终端内展示表格

我们可以使用 select 语句从数据库中查出来内容,然后使用 list() 方法就可以转换成可以循环的列表。但是如何优雅的在终端内展示表格呢?这里,我使用了一个 python 的库 prettytable 来解决我的问题。

不使用 list() 函数也可以循环的。

演示如下:

from prettytable import PrettyTable# 从数据库拿到结果,转换成列表res = list(c.execute(select))# 给输出的表格设定表头,有几列就设定几个x = PrettyTable(['id','name','password','time'])# 可以给指定列设定文字对齐,默认是居中对齐,下面是改成了 left 左对齐x.align['name'] = 'l'# 设定表格内填充为 1 个空格,让表格可读性更高x.padding_width = 1# 循环数据for row in res:    # 插入每一行的数据    x.add_row(list(row))# 打印表格print(x)

好,这样我们就可以输出优雅的表格了。其结果如下:

+----+--------------+------------+---------------------+| id | name         |  password  |         time        |+----+--------------+------------+---------------------+| 4  | 123          |  zTAT8DCU  | 2017-12-20 08:31:35 || 3  | sunmingyuan2 | TxmKZt:44s | 2017-12-20 05:11:36 || 2  | sunmingyuan  | /t22664Q44 | 2017-12-20 05:11:22 |+----+--------------+------------+---------------------+

其他内容都是基础的 sql 语句的内容。更多 sql 内容可以访问 http://www.w3school.com.cn/sql/index.asp 获取。

补充查看和删除密码的管理脚本 seepw.py 代码

上面我们的 db.py 脚本中,除了生成密码的脚本中我们需要的插入语句外,我还写了查看以及删除语句的函数。我使用了另外一个脚本 seepw.py 来实现相应的功能。其代码如下:

#!/usr/bin/env python3# -*- coding: UTF-8 -*-import dbimport argparseif __name__ == '__main__':    parser = argparse.ArgumentParser()    parser.description='This program is used to manage the password saved in the database'    parser.add_argument("-v", "--version",action='version', version='%(prog)s 1.0')    group = parser.add_mutually_exclusive_group()    group.add_argument("-i", "--id", help="The ID of the password you want to look at")    group.add_argument("-n", "--name", help="The NAME of the password you want to look at")    group.add_argument("-d", "--delete", help='Delete mode, the parameter is ID')    args = parser.parse_args()    name = args.name if args.name else False    pId = args.id if args.id else False    dId = args.delete    if dId:        if dId.isdigit():            db.deleteDb(dId)        else:            print('Error: The parameters of the delete mode must be number')    else:        db.selectDb(pId,name)

这个脚本没什么更多的解释,只是去配置了 argparse 库的各种参数然后判断用户是想查看还是删除,然后执行对应的方法即可。

补充生成密码的修改

首先是去除原有的使用文本文件存储的所有代码,引用我们的 db.py 文件,然后在需要插入密码到数据库的地方使用下面的方法即可往数据库中插入保存的数据。

db.insertDb(name,passwd)

接下来我会抽时间写一个一键安装脚本,到时候放到 github 上面,给大家使用。

本文由 FungLeo 原创,允许转载,但转载必须保留首发链接。

阅读全文
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝贝详情怎么改不了怎么办 改详情页后被删除宝贝怎么办 淘宝网商贷生意不好还不了怎么办 英国遗失在酒店物品怎么办 班福法则首位是0怎么办 同事能力比你强怎么办 新买的木板床响怎么办 笔记本键盘驱动坏了怎么办 云柜快递超时了怎么办 毕业设计被老师发现抄的怎么办 地板颜色太深了怎么办 皮质鞋子破皮了怎么办 吃了蜘蛛丝会怎么办 南京高二分班不公平怎么办? 高中分班考试没考好怎么办 实木门上的伸缩缝太深怎么办 mac点关机没反应怎么办 被压倒扁的易拉罐怎么办 白色车漏底漆了怎么办 客厅对着卧室门怎么办 老公不上进还懒怎么办 二胡按弦手指分不开怎么办 酷塑做完后疼痛怎么办 冷冻治疗后水泡破了怎么办 冷冻治疗的水泡破了怎么办? 冷冻治疗水泡破了怎么办 脚上冷冻后起泡怎么办 刺猴冷冻后起泡怎么办 隔壁太吵怎么办阴招 楼上有小孩太吵怎么办 捷达小水管睹了怎么办 楼房下水管冻了怎么办 一楼地面很潮湿怎么办 新房子地面有裂缝怎么办 地砖下面的下水管漏水怎么办 速冻饺子冻在一起了怎么办 牛排泡水解冻了怎么办 饺子都粘一起了怎么办 把桃子放冷冻了怎么办 抖音小视频连不上网怎么办 网络视频连不上网怎么办