一个简单数据管理python项目教程

前言

一年多以前,我在公司有段时间帮忙做过python的新手培训课程(当然是在下班后),虽然我根本就算不上python高手,但是面对对于编程一无所知的初学者我还是绰绰有余的。后面领导希望能做一个样品管理工具作为最终学习的验收成果,而这篇这文章就是我为当时项目提供一个新手教程。

实际上整个项目的基本设计方案也是我提供的,其功能很简单,主要是对样品自身的信息整理分类、以及样品的借入借出做一个管控和信息记录,不过项目有一些强制的要求:

  1. 需要用python编写
  2. 需要有窗口图形界面
  3. 需要用数据库管理数据信息

于是我也针对性的从以下三点出发做简单的介绍:

  1. python的实用基础知识
  2. PyQt的使用
  3. MySQL connector的使用

以下就是我当时文章内容了(提到的书是指:《Python语言及其应用(美Lubanovic 2016)》)。

1. Python基础知识

1.1 模块的导入

在python的程序中,要使用第三方模块的功能,都需要先导入该模块。关于import的部分详细说明,查看书96页。这里只提示一些注意点:

  1. 使用自己写的其他python文件中的函数,也要先导入
  2. 导入的模块只有放在本目录与python环境中的默认目录,才能导入
  3. 如果需要导入其他目录的模块,可以用sys.path.append(),将这个模块的路径添加到查找路径中,就可以导入了。

1.2 Python的类

在书的第6章,有整整一章的内容讲解类的知识点,所以我这里只是提示一些使用时的注意点:

  • 类用class定义,它其中的每一个成员函数和每一个成员变量都需要在其参数中加self,当使用这些函数时也需要使用self.的形式来调用:
  • 类的成员变量的作用域存在于整个类,使用self.的形式可以在各个成员函数中使用
  • 类中的__init__函数是类的默认初始化函数(构造函数),在类的对象被创建时自动调用,因此一些类初始操作都放在这个函数中:

1.3 用函数返回多个值

在python中,函数是可以返回多个值的,当函数返回多个值时,实际上时返回的一个元组,当接收这样的返回值时除了用一个参数接收外,还可以用多个参数接收:

1
2
3
4
5
6
7
8
def testFuntion():
ret1 = "return data"
ret2 = 23
ret3 = [23,65,90]
return ret1, ret2, ret3

res = testFuntion()
data1,data2,data3 = testFuntion()

1.4 Python中的线程操作

在项目中,连接数据库可能需要很长的时间,单线程的操作很可能导致程序卡住很长时间无法响应。在这样情况下,我们一般会新创建一个线程,在线程中执行数据库连接的操作。

在Python中创建线程的最基本操作可以固定如下:

1
2
3
4
5
6
7
8
9
10
11
# 导入线程模块
from threading import Thread

# 线程开始时执行的函数
def connectThread():
print('conneting')

# 创建线程
th = Thread(target=connectThread)
th.setDaemon(True)
th.start()

2. PyQt的使用

2.1 PyQt简介

PyQt是Qt的Python版本,一般在Python发布版本(WinPython和Anaconda)中都会有带有,官方原生的Python则需要自己安装。原生的Qt是C++版的,当前主流Qt使用的是两个版本:Qt4和Qt5,对应Python的版本为PyQt4和PyQt5,在我们的项目中使用PyQt5。

使用Qt设计界面有一个很好用的工具,那就是Qt Designer。它提供可视化的界面设计环境,让能够让开发者更快速、简单的设计和布局界面。

2.2 PyQt使用基本步骤

下面,我将使用PyQt生成一个最简单的窗口,通过以下代码我们可以看到,仅仅需要五个简单的步骤就可以完成。这五个步骤可以看成使用PyQt的一个固定的模式,要创建其他更复杂的窗口时,只是在此基础上稍作修改然后增加新窗口的部分代码而已。

注:在jupyter环境下,直接运行以下代码,就可以得到一个新的窗口

1
2
3
4
5
6
7
8
9
10
11
12
import sys

# 第一步,导入PyQt5或者它的子库
from PyQt5.QtWidgets import QApplication, QMainWindow
# 第二步,创建一个Qt应用程序
app = QApplication(sys.argv)
# 第三步,创建一个QMainWindow窗口
mwind = QMainWindow()
# 第四步,显示创建的窗口
mwind.show()
# 第五步,开启消息循环
app.exec()

2.3 使用Qt Designer设计界面

前面说过,Qt Designer是Qt提供的一个可视化界面设计工具,使用Qt Designer不管是布局窗口或者调整控件的大小和位置,还是增加或者删除控件,都只需要简单拖动鼠标即可。

Qt Designer设计的界面保存的文件,是一个XML格式后缀名以.ui结尾的文件,设计时使用到的资源(如图片)将保存为以.qrc为后缀的资源文件。当我们的代码要使用这些窗口时,需要使用Qt给定的工具将ui文件和资源转化Python代码能够使用的.py文件:

  • pyuic5.bat:将.ui文件转化为.py文件
  • pyrcc5.exe:将.qrc文件转化为.py文件

在Windows系统中,可以在命令行中,执行以下转化命令:

ui文件的转化(假定ui文件名为MainWindow.ui):

1
pyuic5.bat -o Ui_MainWindow.py MainWindow.ui

资源文件的转化(假定pyrcc5.exe的路径如下,资源文件名为res.qrc):

1
D:\WinPython\python-3.4.4\Lib\site-packages\PyQt5\pyrcc5.exe -o res.py res.qrc

当然,你可以将这些转化命令写到python代码或者bat脚本中,然后一下执行一系列的转化。另外对于PyCharm的使用者,可以使用PyCharm封装了这两个命令的菜单来执行。

2.4 使用自己设计的窗口

在2.2中生成的窗口只是Qt中默认的窗口,在实际项目中我们肯定是需要使用自己设计的窗口的,我们只需要做两步修改即可:

  1. 创建一个新的窗口类(它同时继承于Qt的默认窗口和我们自己的设计的窗口),
  2. 将2.2中的代码,创建的窗口改为自己新建的窗口类

假定我们从2.3节转化得到的窗口文件为Ui_MainWindow.py,则我们需要增加的代码如下:

1
2
3
4
5
# 新建自己的窗口类
class MyUi(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MyUi, self).__init__()
self.setupUi(self)

将mwind = QMainWindow()改为如下代码:

1
mwind = MyUi()

注:由于以上两段代码不全,所以在jupyter中不能执行

2.5 在代码中使用控件

在窗口设计中,窗口本身和窗口上分布的控件是两大不同的组成部分,窗口自身可能会有菜单栏、工具栏、状态栏,但是更丰富的功能还是需要使用控件来完成。这里例举一些常见的控件以及它对应作用:

  • QLabel:显示文字,提示作用
  • QLineEdit:单行文字输入,输入文字作用
  • QTextEdit:多行文件输入或显示,输入文字或显示信息的作用
  • QPushButton:按钮,提供用户操作的方法
  • QRadioButton:单选输入,提供选择输入
  • QComboBox: 下拉列表的形式,提供单选输入
  • QTabelView:显示表格信息,提供表格数据显示

使用控件时要注意以下几点:

  1. 控件的名字:在代码使用控件都是用控件的名字,所以控件命名时在同一窗口中不能重复了
  2. 控件的方法:每种控件都有自己不同的作用,他们的拥有的方法也可能不一样,这个需要在Qt的官方文档中查询(如QLineEdit的页面为: http://doc.qt.io/qt-5/qlineedit.html
  3. 控件的消息:控件在发生改变时可能会产生消息,控件拥有消息的类型需要在官方文档对应的页面的“Singals部分”查询

那么具体怎么在代码中使用这些控件呢?仍然以2.4中的例子为例,为获取QLineEdit的文字并改变其中的值,你需要在MyUi类中合适的地方加入:

1
2
3
4
# 获取名为lineEdit的QLineEdit控件的输入的文字
textStr = self.text()
# 设置lineEdit的文字,为在原有输入信息的前面加上“你输入了:”
self.setText("你输入了:"+textStr)

注意:尽管每个控件的很多都不一样,但是也有一些方法是一样的,如上面所示的text()和setText()函数,很多控件或缺它的文字和设置它的文字的方法都是这两个函数

那么又怎么让控件的信号关联到自己的消息处理函数上呢?以名为button的QPushButton为例,要处理它的用户点击消息,要在MyUi类中加入代码如下:

1
2
# OnLoginBtnClicked2是MyUi类中自己写的消息处理函数,clicked就是QPushButton控件中的一种信号,用connect可以将新号和处理函数关联起来
self.button.clicked.connect(self.OnLoginBtnClicked2)

3. Python中MySQL connector的使用

3.1 MySQL connector简介

在Python访问MySQL数据库需要用它的第三方库,在我们的项目中用的是mysql connector,利用它能够比较简单的实现MySQL数据库操作。一般在Python的发布版本中都自带mysql connector,官方原生的Python需要自己安装。

3.2 MySQL connector使用的基本流程

以下是mysql connector使用的基本流程(测试我的本地数据库服务器,地址:127.0.0.1,用户:testuser,密码:123456,数据库:test,端口:3306):

注:在jupyton环境下,可以直接执行,不过需要将数据库服务器的参数设置为自己实际情况的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 第一步,导入mysql.connector
import mysql.connector

# 第二步,连接数据库
db_server = '127.0.0.1'
db_user = 'testuser'
db_pw = '123456'
db_port = '3306'
db_database = 'test'
cnx = mysql.connector.connect(user=db_user, password=db_pw, host=db_server, database=db_database,port=db_port)

# 第三步, 获取cursor
cur = cnx.cursor()

# 第四步, 执行sql语句
cur.execute("show databases")

# 第五步,获取执行的结果
ret = cur.fetchall()

# 第六步, 关闭连接
cur.close()
cnx.close()

print("数据库服务器有库:",ret)

从上面,我们可以看到利用mysql connector操作数据库服务器的基本流程为6步,我们可以认为上面操作是所有操作的基础。其中第二步、第三步在可以认为是数据库的连接部分,在使用数据库前一定要先连接成功。第六步是关闭数据库连接的操作,在所有数据库操作完成后执行。第四步和第五步是实际数据库操作部分,在数据库连接成功后并且在没有关闭前,可以一直执行。

我们对数据的操作实际上都是用sql语句去做的,而上面代码的第四步就时执行sql语句,我们只要改变execute函数中的sql语句字符串就可以将它变成执行其他功能的操作。

3.3 MySQL connector执行sql语句的两种类型

使用mysql connnector执行数库语句有两种类型:

  1. 对数据库进行查询,需要返回数据
  2. 对数据库进行修改,不需要返回数据的

这两种类型,在使用mysql connector时会有稍许的差异,对应3.2中的代码中,不同的部分在第五个步骤,其他部分都一样。

对于第一种类型,使用fetch系列函数来获取数据:

1
ret = cur.fetchall()

对于第二种类型,使用commit来提交修改:

1
cnx.commit()

3.4 额外的sql语句知识

3.4.1 条件查询

使用where,可以根据条件查询得到对应的数据,如:查询用户名为“李四”的人的密码:

1
select password from usertable where username = "李四"

可以用and连接两个条件,如:查询用户名为“李四”同时年龄大于20的人的密码:

1
select password from usertable where username = "李四" and age > 20

3.4.2 使用数据库内置函数

数据库中有一些内置的函数,可以在sql语句中使用

  • count(): 统计查询结果的个数,如:select count(username) from usertable
  • max()、min(): 计算查找结果的最大、最小的一个返回,如:select max(age) from usertable
  • length(): 计算查找的字符长度,如:select username from usertable where length(username) < 6
Compartir