python:GUI图形化数据库巡检工具
问题描述:时间过得真快,一眨眼又一个月过去,2022又过去大半,7月的尾巴,终于稍微做出来点 东西,本人也不是开发,也是在不断学习的一枚小白。这次使用tkinter制作了一个mysql的巡检工具,使用图形化操作,边学边操作,一路踩坑,写的不好,但是能交出来一个东西,学习的过程中加深了对class的理解,学习了tkinter布局,如何连接数据库等等。
python:Python 3.8.1
数据库对象:MySQL
一、实现效果
二、问题解决
过程中遇到的问题
1.因为做的是数据库巡检系统,所以登录的账号往往是权限较大的比如root,然后如何去校验root账号,跟正常的管理系统不一样,不是创建好用户和密码表,然后去比对。root是存放在数据库系统中的,没办法去校验root的用户和密码。这里的root是作为参数传进来的,所以如何去比对权限较大的用户呢?
2.显示页面如何去加载数据库中的查询结果呢?按理说应该跟简单,取得数据库查询的返回值,然后加载在页面中。但最后这个显示结果还不是很理想
3.数据库登录的时候如何返回mysql连接给的报错值,如果只设置判断是否登录成功失败很简单,但是在返回mysql报错值的时候如何返回给前台呢
三、代码部分
LoginMain.py
登录类
- class Application(Frame):
- username = ''
- password = ''
- ip = ''
- port = ''
- def __init__(self,master=None):
- super().__init__(master)
- self.master = master
- self.pack()
- self.createWidget()
- def createWidget(self): #创建组件容器
- page = Frame(self)
- page.pack()
- self.usernameGet = StringVar()
- self.usernameGet.set('root')
- self.passwordGet = StringVar()
- self.passwordGet.set('zabbix.9.31')
- self.ipGet = StringVar()
- self.ipGet.set('192.168.163.21')
- self.portGet = StringVar() #这里如果设置IntVar,GUI上会显示0,整数可以为0,不能是空
- self.portGet.set('33306')
- Label(page).grid(row=0,column=0)
- Label(page,text='账户:').grid(row=1,column=1)
- Entry(page,textvariable=self.usernameGet).grid(row=1,column=2)
- Label(page,text='密码:').grid(row=2,column=1)
- Entry(page,textvariable=self.passwordGet,show='*').grid(row=2,column=2)
- Label(page,text='IP地址:').grid(row=3,column=1)
- Entry(page,textvariable=self.ipGet).grid(row=3,column=2)
- Label(page,text='端口:').grid(row=4,column=1)
- Entry(page,textvariable=self.portGet).grid(row=4,column=2)
- Button(page,text='登录',command=self.login_check).grid(row=5,column=1,pady=10)
- Button(page,text='退出',command=page.quit).grid(row=5,column=2)
- def login_check(self):
- #设置登录退出按钮
- i = self.ipGet.get()
- p = int(self.portGet.get())
- u = self.usernameGet.get()
- pa = self.passwordGet.get()
- db_name = 'mysql'
- #实例化Mysql类
- mysqlLogin = Mysql(i,p,u,pa,db_name) #这里不能用mysqllogin对象做布尔值判断,只要输入正确,他的布尔值一直是true
- results = mysqlLogin.select('select @@version')
- print(bool(mysqlLogin));print(bool(results))
- if results:
- messagebox.showinfo('提示', '连接成功,正在为您生成巡检报告')
- # print(type(i),type(p),type(u),type(pa))
- self.destroy()
- MainPage(root)
- mysqlLogin.show()
数据库连接类
- class Mysql(object):
- # mysql 端口号,注意:必须是int类型
- def __init__(self, host, port, user, passwd, db_name):
- self.host = host
- self.user = user
- self.passwd = passwd
- self.port = port
- self.db_name = db_name
- def select(self, sql):
- """
- 执行sql命令
- :param sql: sql语句
- :return: 元祖
- """
- try:
- conn = pymysql.connect(
- host=self.host,
- user=self.user,
- passwd=self.passwd,
- port=self.port,
- database=self.db_name,
- charset='utf8',
- #cursorclass=pymysql.cursors.DictCursor
- )
- cur = conn.cursor() # 创建游标
- # conn.cursor()
- cur.execute(sql) # 执行sql命令
- #print(type(cur.execute(sql)))
- res = cur.fetchall() # 获取执行的返回结果
- #print(type(res))
- cur.close()
- conn.close()
- # print(res)
- return res
- except Exception as e:
- messagebox.showerror('提示',e)
- return False
- def show(self):
- sql1 = "show global variables"
- # sql2 = "show master status;"
- # sql3 = "SELECT table_schema,SUM((AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH))/1024 AS total_KB FROM information_schema.TABLES GROUP BY table_schema ORDER BY total_KB DESC ;"
- res1 = dict(self.select(sql1))
- # res2 = self.select(sql2)
- # res3 = self.select(sql3)
- filename = r"D:\{}".format('mysql_check.txt')
- with open(filename, mode='w', encoding='utf-8') as f:
- # 检查MySQL版本
- #print("\033[1;32m当前数据库的版本是:\033[0m" + res1['version'])
- f.write("当前数据库的版本是:" + res1['version'] + "\n")
- f.write("当前数据库的version_comment是:" + res1['version_comment'] + "\n")
- f.write("当前数据库的version_compile_machine是:" + res1['version_compile_machine'] + "\n")
- f.write("当前数据库的version_compile_os是:" + res1['version_compile_os'] + "\n")
- f.write("当前数据库的version_compile_zlib是:" + res1['version_compile_zlib'] + "\n")
- f.write("当前数据库的sql_mode是:" + res1['sql_mode'] + "\n")
- # 检查MySQL端口
- #print("\033[1;35m当前数据库的端口是:\033[0m" + res1['port'])
- f.write("当前数据库的端口是:" + res1['port'] + "\n")
- # 检查server_id
- #print("\033[1;32m当前数据库的server_id是:\033[0m" + res1['server_id'])
- f.write("当前数据库的server_id是:" + res1['server_id'] + "\n")
- # 检查basedir目录
- #print("\033[1;32m当前数据库的basedir在:\033[0m" + res1['basedir'])
- f.write("当前数据库的basedir在:" + res1['basedir'] + "\n")
- # 检查datadir目录
- #print("\033[1;35m当前数据库的datadir在:\033[0m" + res1['datadir'])
- f.write("当前数据库的datadir在:" + res1['datadir'] + "\n")
- # 检查tmpdir目录
- #print("\033[1;32m当前数据库的tmpdir在:\033[0m" + res1['tmpdir'])
- f.write("当前数据库的tmpdir在:" + res1['tmpdir'] + "\n")
- #pid_file
- f.write("当前数据库的pid_file在:" + res1['pid_file'] + "\n")
- #optimizer_switch
- f.write("当前数据库的optimizer_switch:" + res1['optimizer_switch'] + "\n")
- #mysqlx_socket
- f.write("mysqlx_socket:" + res1['mysqlx_socket'] + "\n")
- #log_bin_basename
- f.write("当前数据库的log_bin_basename在:" + res1['log_bin_basename'] + "\n")
- #log_error
- f.write("当前数据库的log_error在:" + res1['log_error'] + "\n")
- #slow_query_log_file
- f.write("当前数据库的slow_query_log_file在:" + res1['slow_query_log_file'] + "\n")
MainPage.py
- class MainPage:
- def __init__(self,master: tk.Tk):
- self.root = master
- self.root.title('数据库巡检系统')
- self.root.geometry('600x400')
- self.create_page()
- def create_page(self):
- self.about_frame = AboutFrame(self.root) #调用views中的aboutframe类,显示关于的信息
- # tk.Label(self.about_frame,text = '关于作品:数据库巡检系统').pack()
- # tk.Label(self.about_frame,text = '关于作者:我爱睡莲').pack()
- # tk.Label(self.about_frame,text = '版权所有:https://www.cnblogs.com/houzhiheng/').pack()
- self.check_frame = CheckFrame(self.root)
- menubar = tk.Menu(self.root)
- menubar.add_command(label='巡检结果',command=self.show_check)
- menubar.add_command(label='关于',command=self.show_about)
- self.root['menu'] = menubar
- def show_check(self):
- self.check_frame.pack()
- self.about_frame.pack_forget() #选择性遗忘其他加载过的页面,要不然都会加载在页面当中
- def show_about(self):
- self.about_frame.pack()
- self.check_frame.pack_forget()
views.py
显示关于部分类
- class AboutFrame(tk.Frame):
- def __init__(self,root):
- super().__init__(root)
- tk.Label(self, text='Production:数据库巡检系统').pack()
- tk.Label(self, text='Author:我爱睡莲').pack()
- tk.Label(self, text='Version:1.0').pack()
- tk.Label(self, text='@Copyright:https://www.cnblogs.com/houzhiheng/').pack()
显示数据库巡检结果类
- class CheckFrame(tk.Frame):
- def __init__(self,root):
- super().__init__(root)
- # tk.Label(self, text='巡检结果').pack()
- self.table_view = tk.Frame()
- self.table_view.pack()
- self.create_page()
- tk.Button(self,text='保存文件',command=self.save_data_frame).pack(anchor=tk.E,pady=5)
- def create_page(self):
- # self.tree_view = ttk.Treeview(self,show='headings')
- # columns = ("check_results")
- # columns_values = ("数据库巡检报告")
- # top = Tk() # 设置窗口
- # sb = Scrollbar(top) # 设置窗口滚动条
- # sb.pack(side=RIGHT, fill=) # 设置窗口滚动条位置
- # self.sb = Scrollbar()
- # self.sb.pack(side=RIGHT,fill= Y)
- # self.tree_view = ttk.Treeview(self,show='headings',columns=columns)
- # self.tree_view.column('check_results',width=500,anchor='center')
- # self.tree_view.heading('check_results',text=columns_values)
- # self.tree_view.pack(fill=tk.BOTH,expand=True)
- # self.show_data_frame()
- with open(r'D:\mysql_check.txt', 'r', encoding='utf-8') as f:
- lines2 = [l.split() for l in f.readlines() if l.strip()]
- # 滚动条初始化(scrollBar为垂直滚动条,scrollBarx为水平滚动条)
- scrollBar = Scrollbar(self)
- scrollBarx = Scrollbar(self, orient=HORIZONTAL)
- # 靠右,充满Y轴
- scrollBar.pack(side=RIGHT, fill=Y)
- # 靠下,充满X轴
- scrollBarx.pack(side=BOTTOM, fill=X)
- lb = Text(self, width=100, height=25,)
- lb.pack()
- # db = Mysql('192.168.163.21', 33306, 'root', 'zabbix.9.31', 'mysql')
- # res = db.show()
- textvar = "1:{} \n2:{}\n3:{}\n4:{}\n5:{}\n6:{}\n7:{}\n8:{}\n9:{}\n10:{}\n11:{}\n12:{}\n13:{}\n14:{}\n15:{}"\
- .format(lines2[0],lines2[1],lines2[2],lines2[3],lines2[4],lines2[5],lines2[6],lines2[7],lines2[8],lines2[9],lines2[10],lines2[11],lines2[12],lines2[13],lines2[14],lines2[15],lines2[16])
- lb.insert('insert', textvar + '\n')
- lb.update()
- # 而当用户操纵滚动条的时候,自动调用 Treeview 组件的 yview()与xview() 方法
- # 即滚动条与页面内容的位置同步
- scrollBar.config(command=lb.yview)
- scrollBarx.config(command=lb.xview)
- def show_data_frame(self): #把查询的内容输出到屏幕上来
- pass
- def save_data_frame(self):
- messagebox.showinfo('提示','您的文件已保存在D:\mysql_check.txt中!')
四、结论与收获
问题处理:
1.如何去对比root登录是否成功呢,从上面代码可以看到,我没法去直接登录数据库去校验用户名和密码,但是我可以让用户名登录成功去执行命令来判断是否登录成功,如果root登陆并且成功执行命令,我就返回一个结果为TRUE,如果执行失败,就返回一个结果为FALSE,这条命令是去查询数据库自身版本得到,任何用户都可以执行
2.在屏幕上输出巡检的结果,本来取得数据库返回值然后给屏幕上就可以了,但是我的views.py调用class MySQL类失败,所以最后直接把查询结果保存在了文件中,前台输出的时候打开文件,然后调整文件格式就输出了,败笔啊这一步
3.将mysql连接返回的报错做成异常处理即可,只不过当时做的时候逻辑有一点问题一直没显示成功
结论收获:
本来是想做一个全套的数据库巡检GUI系统,桌面版本的已经做好了,但是没有到光做一个GUI+mysql版本的就花费了两周时间了,不过这个大体结构成型,后边如果想做应该会简单些。这次更加深刻了解了面向对象,上学没学好,毕业了都得补回来
python:GUI图形化数据库巡检工具的更多相关文章
- python GUI图形化编程-----wxpython
一.python gui(图形化)模块介绍: Tkinter :是python最简单的图形化模块,总共只有14种组建 Pyqt :是python最复杂也是使用最广泛的图形化 Wx ...
- MariaDb数据库管理系统学习(二)使用HeidiSQL数据库图形化界面管理工具
HeidiSQL 是一款用于简单化的 MySQL server和数据库管理的图形化界面.该软件同意你浏览你的数据库,管理表,浏览和编辑记录,管理用户权限等等.此外,你能够从文本文件导入数据,执行 SQ ...
- 黑马程序员:Java基础总结----GUI图形化界面
黑马程序员:Java基础总结 GUI图形化界面 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! GUI(Graphical User Interface)图形化界 ...
- [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit
[.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit 读前必备: 接上篇: 分布式版本控制系统Git——使用GitS ...
- Atiti qq空间破解(3)------------gui图形化通用cli执行器atiuse
Atiti qq空间破解(3)------------gui图形化通用cli执行器atiuse 结构:::命令行+以及反馈log框1 cli_guiUI/index.htm1 /AtiPlatf_c ...
- zookeeper图形化的客户端工具
追加一个zookeeper图形化的客户端工具: 1.zookeeper图像化客户端工具的下载地址:https://issues.apache.org/jira/secure/attachment/12 ...
- 品味性能之道<六>:图形化SQL分析工具
在上一章里,重点分享了命令行SQL分析工具的使用方法.在本章将重点分享PL/SQL的SQL分析工具. 一.如何打开PL/SQL执行计划 开启PL/SQL这工具,推荐如下方法: 点击 ...
- zookeeper系列(一)zookeeper图形化的客户端工具
追加一个zookeeper图形化的客户端工具: 1.zookeeper图像化客户端工具的下载地址:https://issues.apache.org/jira/secure/attachment/12 ...
- python数据图形化—— matplotlib 基础应用
matplotlib是python中常用的数据图形化工具,用法跟matlab有点相似.调用简单,功能强大.在Windows下可以通过命令行 pip install matplotlib 来进行安装. ...
随机推荐
- 网络:Tor
洋葱路由催生了暗网的产生 1995年,美国海军研究实验室的科学家开始开发一套匿名系统,可以避免人们在互联网上的行迹被追 踪到.由于在该系统中,数据被层层密码保护,这个技术被称为叫作"洋葱路由 ...
- 好客租房39-react组件基础总结
1组件的两种创建方式:函数组件和类组件 2无状态函数组件 负责静态结构展示 3有状态组件 负责更新ui 让页面动起来 4绑定事件注意this指向问题 5使用受控组件创建表单 6完全利用js语言的能够力 ...
- linux篇-linux mysql数据库定时备份
1在linux上面创建一个文件夹,并且进行备份 cd /home mkdir backup cd backup 2创建一个脚本 Vi imaginebase.sh #!/bin/bash mysqld ...
- 腾讯产品快速尝鲜,蓝鲸智云社区版V6.1灰度测试开启
这周小鲸悄悄推送了社区版V6.1(二进制部署版本,包含基础套餐.监控日志套餐),没过一天就有用户来问6.1的使用问题了.小鲸大吃一鲸,原来你还是爱我的. 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行 ...
- Bean Validator
Bean Validator 关于Jakarta EE 2018年03月, Oracle 决定把 JavaEE 移交给开源组织 Eclipse 基金会,并且不再使用Java EE这个名称. 因此jav ...
- vue内容拖拽放大缩小
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- BUUCTF-菜刀666
菜刀666 这题和之前做过的流量题不同,对我还是有些难度.看了看大佬的wp才做出来的 wireshark打开流量包,一开始只是单纯过滤http,包很多,看花了眼,看了好多也没觉得有啥异常. 后面才知道 ...
- BUUCTF-神秘龙卷风
神秘龙卷风 通过提示知道压缩包密码是四位纯数字,通过爆破得到 得到一串编码 看样子应该是brainfuck编码 flag{e4bbef8bdf9743f8bf5b727a9f6332a8}
- Python基础学习笔记_01
Python的介绍 1989年圣诞节创造,1991年正真出生,目前更新到3.0版本 具有最庞大的"代码库",人称"胶水语言",无所不能 一种跨平台的计算机程序设 ...