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 来进行安装. ...
随机推荐
- 购物车+ATM项目(图形化)
项目下载 项目目录结构 运行效果 seetings.py import logging import logging.config # 定义日志输出格式 开始 import os standard_f ...
- Tomcat配置安装
1.tomcat是什么? 是由JAVA开发的开源且免费,主要是用于web服务器,是中间件.主要用于中小型企业 2.tomcat安装 安装jdk,可以rpm或者官网安装,安装完配置java环境变量,打开 ...
- leetcode 142. Linked List Cycle II 环形链表 II
一.题目大意 https://leetcode.cn/problems/linked-list-cycle-ii/ 给定一个链表的头节点 head ,返回链表开始入环的第一个节点. 如果链表无环,则 ...
- 记 iTextSharp 剪裁 PDF 指定区域的方法
原文 引用 itextsharp 5.5.13.2 itextsharp.xtra 5.5.13.2 方法 /// <summary> /// 截取pdf文件,例如把A4截出指定的A6区域 ...
- 520表白小程序设计Python代码详解(PyQt5界面,B站动漫风)
摘要:介绍一个动漫风的表白小程序,界面使用Python以及PyQt实现,界面样式经过多次美化调整,使得整体清新美观.本文详细介绍代码设计和实现过程,不仅是居家表白必备,而且适合新入门的朋友学习界面设计 ...
- (数据科学学习手札137)orjson:Python中最好用的json库
本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,我们在日常使用Pytho ...
- sklearn练习1 回归
from sklearn.svm import SVR from sklearn.pipeline import make_pipeline from sklearn.preprocessing im ...
- 【Redis】事件驱动框架源码分析(多线程)
IO线程初始化 Redis在6.0版本中引入了多线程,提高IO请求处理效率. 在Redis Server启动函数main(server.c文件)中初始化服务之后,又调用了InitServerLast函 ...
- 解决Invalid bound statement (not found)的异常
今天在搭建框架的时候,报了一个Invalid bound statement (not found)的异常 经过分析,得出原因: 我的mybatis相关的dao和mapper.xml是通过逆向工程生成 ...
- 14.Nginx搭建及优化
Nginx搭建及优化 目录 Nginx搭建及优化 Nginx服务基础 概述 Nginx和Apache的优缺点比较 编译安装Nginx服务 添加Nginx系统服务 Nginx服务配置文件 nginx服务 ...