Python — 学生成绩管理

Python — 学生成绩管理

摘要

  本次实验要求使用python语言,读取现有的班级花名册,写入SQlite数据库,逐个显示每一个学生的学号姓名,输入其python、英语等课程的成绩,写入SQLite数据库。全部记录结束后,计算大家的总分、名次,并显示整个花名册。
  在实验过程中,我首先分析实验要求,决定使用”将Excel文件导入数据库、录入学生各科成绩信息、计算总成绩、显示输出、导出文件”的基本思路,使用cmd和Notepad++环境进行实验。在”录入信息方式”,”输出显示方式”,”整合代码”,“导出为Excel文件”等方面进行代码优化,最终完成学生成绩管理程序的编写,完成实验要求。

关键字:Python SQLite数据库 文件读写 学生信息管理

一、总体思路

   读取现有的班级花名册,写入SQlite数据库,逐个显示每一个学生的学号姓名,输入其python、英语等课程的成绩,写入SQLite数据库。全部记录结束后,计算大家的总分、名次,并显示整个花名册。
Python — 学生成绩管理_第1张图片

图1 流程图

二、设计思路

2.1数据录入部分

  首先需要创建一个数据库表格,用于储存学生的数据。之后,读出excel表中的数据,将数据插入到数据库表格中。然后手动或自动录入成绩信息。

2.2数据计算部分

  读取数据库中各科成绩的信息,求和得出总成绩,将总成绩记录并更新表格。

2.3输出部分

  将数据库表格中的数据,以一定的格式进行输出,并生成excel文件保存。

三、具体实现过程

3.1读取excel数据

  要读取excel文件,需要使用openpyxl模块,该模块是一个用于读取/写入Excel 2010 xlsx / xlsm / xltx / xltm文件的Python库。可以使用pip命令安装该模块。
Python — 学生成绩管理_第2张图片

图2 安装openpyxl模块

  安装完成后,就可以执行命令,读取excel表格中的数据了。
Python — 学生成绩管理_第3张图片

图3 读取文件数据

  在上图中,使用load_workbook()命令,打开了名为”DK172register.xlsx”的工作簿,使用.worksheet[0],选择第一张工作表。使用for语句对工作表内的数据循环输出。于是,程序就会将表格中的每行数据,以元组的形式输出。其中包括学号和姓名信息。

3.2创建数据库表格

  可以读取数据之后,我们需要创建一个数据库表格,用于储存读到的文件。
Python — 学生成绩管理_第4张图片

图4 创建表格

  上图中,使用sqlite3模块,创建了一个名为”class.db”的数据库对象,之后,在数据库中创建了一个名为”DK172”的表格。该表格包含”StudentID、Name、python_score、English_score、Total”这几个表头,分别用来代表”学号、姓名、python成绩、英语成绩、总成绩”。

3.3插入表格数据

  创建表格完成之后,我们就可以将excel中的数据导入到数据库中了。在这里,我也遇到了一些问题。
Python — 学生成绩管理_第5张图片

图5 INSERT报错

  在上图中,我使用sqlite3模块创建数据库,使用openpyxl模块读取到了表格中的文件。将学号信息储存在id变量中,将姓名信息储存在name变量中。想通过INSERT语句及那个这两个信息插入到数据库表格中。没想到程序发生了错误。
  在百度上查找相关资料,发现是INSERT语句的格式不对,经过修改后,再次执行程序:
Python — 学生成绩管理_第6张图片

图6 插入数据

  上面的语句中,我将VALUES中的内容替换为了(%d ‘%s’),并用格式控制字符%将id、name变量中的值传入了VALUES中。程序正常执行,显示了导入数据的情况。为了更加直观的看出数据库中的数据,我使用”DB Brower for SQLite”查看数据库内容。
Python — 学生成绩管理_第7张图片

图7 查看可视化界面

  可以看出,数据已经成功地导入了数据库中。

3.4更新成绩数据

  在将excel表格中的数据导入到数据库之后,就需要插入成绩数据了。一开始我尝试使用INSERT语句进行数据导入,成绩数据导入成功,但是在DB中查看数据库,发现并不是我们想要的结果。
Python — 学生成绩管理_第8张图片

图8 使用INSERT语句插入成绩数据

Python — 学生成绩管理_第9张图片

图9 程序运行结果

  由上图可以看到,刚刚使用INSERT语句插入的随机成绩数据,并不是插入到了我们想要的位置,而是增加了新的数据。所以应该使用其他语句执行该命令。
  于是,我尝试使用UPDATE命令,更新原有表格中的数据,从而实现添加数据的效果。
Python — 学生成绩管理_第10张图片

图10 UPDATE更新数据

  上图中,我首先使用SELECT语句将“DK172”表格中所有的“StudentID”数据取出,并保存在IDs中。接着,使用for语句,将”IDs”中的数据循环取出,使用UPDATE语句,对指定的学生ID进行更新操作。
  可以看出,为了方便测试,程序中代表成绩的数据的”python”和”English”都是随机生成的。现在,我们去”DB Brower for SQLite”查看一下数据库里的内容。
Python — 学生成绩管理_第11张图片

图11 插入随机数据

  可以看出,随机产生的”python”和”English”数据,已经成功插入到了数据库中指定的位置。现在,我尝试为数据库手动输入数据。
  既然已经实现了将随机数据插入到数据库指定位置,要想实现手动输入数据,只需将产生随机数据改为手动输入数据就可以了。
Python — 学生成绩管理_第12张图片

图12 手动输入数据

  将”python”和”English”更改为手动输入,就实现了手动输入数据的功能。但是,如果仅仅修改这些,我们班42人的所有数据都需要手动输入,比较麻烦。所以我希望实现”前40个数据随机产生,后2个数据手动输入”的功能。
  要实现该功能,加一个条件判断语句就可以了,于是编写了下面的函数。
Python — 学生成绩管理_第13张图片

图13 随机加手动数据

  上图的函数,设置了一个变量”con”用来记录循环次数。当循环次数小于40次时,让数据随机产生;当循环次数大于40次时,显示提示并手动输入数据。
Python — 学生成绩管理_第14张图片

图14 查看可视化界面

  在上图中可以看出,最后两组数据确实是我所刚刚手动输入的数据。后面Total字段里的数据,我们可以先不看。那些数据是测试”计算总分”时产生的,与现在演示的功能无关。由于没有更新这些数据,所以这些数据是不正确的。
  现在,已经实现了”导入Excel数据”和”录入分数”功能,下面将尝试进行”计算总成绩”。

3.5计算总分数

  要计算总分数,我想应该首先将每组数据中”python_score”和”English_score”数据取出,相加后记录在一个变量中,再使用UPDATE语句更新这组数据,从而将总分数据插入改组数据。于是编写如下代码:
Python — 学生成绩管理_第15张图片

图15 计算总分数

  上面的代码中,我首先使用SELECT语句,将”DK172”表格中字段为”python_score”和”English_score”的所有数据保存在marks变量中。之后利用for语句,用mark变量逐条取出marks中的数据。于是,在每次循环中,mark[0]表示该组数据的“StudentID”数据;mark[1]表示该组数据的“python_score”数据;mark[2]表示该组数据的“English_score”数据。这样就可以使用UPDATE语句更新总分数据了。
  现在去”DB Brower for SQLite”中查看现在的“DK172”表格。
Python — 学生成绩管理_第16张图片

图16 计算总分并更新数据库

  可以看出,这里所显示的数据与图14所示的程序中的数据一致,说明程序执行成功。

3.6将数据导入excel

  现在就基本上实现了要求的功能,记录排序名次功能我没能实现,但已经可以实现简单的排序,我会在后面介绍。为了将数据库中的文件保存,我希望能将数据库中的文件导出为excel文件。
通过查阅资料和阅读课本例程,我编写了下面的代码去实现该功能。
Python — 学生成绩管理_第17张图片

图17 数据库文件导入excel

  上图的程序中,使用openpyxl模块用于对excel的操作,创建了一个名为“Mysheet“的工作表。连接到数据库之后,使用SELECT语句将”DK172“中的所有数据记录在marks变量中,定义一个名为”head”的元组数据,用于保存表头数据,使用.append()方法将marks中的所有数据全部导入到excel中,最后使用.save()方法,将excel文件保存并命名为”test.xlsx”,从而实现想要的功能。
Python — 学生成绩管理_第18张图片

图18 导入数据到excel

  上图中,可以看出已经将数据导入到了excel,但是字段为”StudentID”的那一列数据,显示的内容不对。查看其中任意一个元素的内容,可以在上方的内容栏看到该元素的内容。可以看出,我们刚刚导入的数据并没有问题,只是excel显示的数字格式不对。将其格式改为分数之后,内容就正常显示了。
Python — 学生成绩管理_第19张图片

图19 excel正常显示内容

3.7代码优化

  接下来,我整理了之前写过的代码。将他们全部整合到了一个文件下,测试执行结果。由于代码稍多,我将它们拆分开进行分析。
Python — 学生成绩管理_第20张图片

图20 part1

  上图定义了两个函数,”create_table()”用来创建一个数据库表格;”export_data()”用来导入花名册里的数据。
Python — 学生成绩管理_第21张图片

图21 part2

  上图定义了两个函数,”update_mark()”用于录入数据,其中的”AutoNum”参数用来限定需要产生多少随机数据;“calculate_sum()”用来计算总成绩。
Python — 学生成绩管理_第22张图片

图22 part3

  上图包含两个函数,”show_data()”用来在命令行显示数据;”export_to_excel()”用来将数据库中的文件导出生成excel表格。
Python — 学生成绩管理_第23张图片

图23 part4

  上图是程序的调用部分,con是全局变量,用在”update_mark()”函数中。之后按顺序调用函数,分布实现想要的功能。
  程序执行之后,首先会导入数据,它会先导入40组随机数据,然后让你输入两组数据。之后会计算总分,完成计算后,会将数据表格显示在命令行界面,最后,生成这些数据对应的excel文件。程序的执行效果还是不错的,但是由于显示的结果太长,我就不在这里截图演示了。我会在附录部分截图展示。

四、待改进部分及期望

4.1排名并记录名次

  上面也曾说过,排名功能还没有实现。我曾尝试使用这样的思路:使用” ALTER”语句为数据库表格添加一个字段用于储存排名名次,之后使用SQLite的“Order By”子句,让所有数据根据总分降序排列,之后在新增的字段里按从1升序,写入名次,最后需要再次使用“Order By”按照”StudentID”升序排列。这样应该可以实现想要的效果,但是我卡在了”再新增字段里写入排名序号”这一步。因为我想使用UPDATE写入这些数据,但是UPDATE需要使用WHERE来描述更新数据的位置,然而经过排名的数据,“StudentID”已经乱序了,也就无法使用UPDATE语句。我也曾尝试使用索引方法,还是没有成功。
  最后,我找到了pandas模块,但通过该模块,我目前也只能实现一个简单的排序功能。
Python — 学生成绩管理_第24张图片

图24 简单排序

  上图中,使用pandas模块,先读取了刚刚生成的excel文件,然后使用.sort_index()方法对数据进行排序,其中的参数”by=Total“表示按照Total排序,”ascending=False”表示降序排列。

4.2数据格式问题

  现在的程序中,包括导入数据和输入成绩数据等,都只是限制在了”特定格式的花名册”和”只有两科成绩”的条件内,可以在“增加程序适应性”方面加以改进。

4.3代码问题

  现在我将代码集成在了一个文件中,但问题是:虽然不同的功能都定义了相应的函数,但是函数之间还是相互依赖,不够独立。以后可以优化代码,降低耦合性。

五、实验总结

  这次实验还是挺有意思的。编程过程中遇到了很多问题,最后通过查找资料等方法也都得到了解决。通过这次实验我也感受到,我在编程或者生活中遇到的问题,别人也有遇到,而他们会把解决方案放到网上与我们分享。所以说,网上的资源太多了。
  但是,网上的资源大多也是提供一个解决方案,想真正能够深入学习,还是得静下心去慢慢学。

六、附录

6.1 read_data.py

from openpyxl import load_workbook
wb = load_workbook(r'C:\Users\ZHJ\Desktop\pywork\DK172register.xlsx')
ws = wb.worksheets[0]
for row in ws.values:
	print(row)

6.2 create_table.py

import sqlite3
conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
c = conn.cursor()
print("Opened databaase successfully..")
c.execute('''CREATE TABLE DK172 (StudentID, Name, python_score, English_score, Total score)''')
conn.commit()
print("Create table successfully..")
conn.close()

6.3 export_data.py

import sqlite3
from openpyxl import load_workbook
conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
c = conn.cursor()
print("Opened databaase successfully..")
wb = load_workbook(r'C:\Users\ZHJ\Desktop\pywork\DK172register.xlsx')
ws = wb.worksheets[0]
for row in ws.values:
	id = row[0]
	name = row[1]
	print(id, name, 'OK')
	c.execute("INSERT INTO DK172 (StudentID, Name) VALUES (%d, '%s')"%(int(id), name))
	conn.commit()
print("Export data successfully..")
conn.close()

6.4 insert_random.py

import sqlite3
import random
conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
c = conn.cursor()
print("Opened databaase successfully..")
c.execute("SELECT StudentID from DK172")
IDs = c.fetchall()
for id in IDs:
	python = random.randint(85, 100)
	English = random.randint(80, 100)
	ID = id[0]
	#print(ID, type(ID))
	c.execute("UPDATE DK172 SET python_score = ?, English_score = ? WHERE StudentID = ?",(python, English, ID))
	conn.commit()
print("Insert data successfully..")
conn.close()

6.5 insert_progra.py

import sqlite3
import random
conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
c = conn.cursor()
print("Opened databaase successfully..")
c.execute("SELECT StudentID from DK172")
IDs = c.fetchall()
for id in IDs:
	ID = id[0]
	print("ID =",ID)
	python = int(input("Please type in the Python score:"))
	English = int(input("Please type in the English score:"))
	c.execute("UPDATE DK172 SET python_score = ?, English_score = ? WHERE StudentID = ?",(python, English, ID))
	conn.commit()
print("Insert data successfully..")
conn.close()

6.6 insert_mixing.py

import sqlite3
import random
con = 0
conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
c = conn.cursor()
print("Opened databaase successfully..")
c.execute("SELECT StudentID from DK172")
IDs = c.fetchall()
for id in IDs:
	ID = id[0]
	if con<40:
		python = random.randint(85, 100)
		English = random.randint(80, 100)
	else:
		if con == 40:
			print("The first 40 data have been randomly generated.\nplease manually enter the following data")
		print("ID =",ID)
		python = int(input("Please type in the Python score:"))
		English = int(input("Please type in the English score:"))
	c.execute("UPDATE DK172 SET python_score = ?, English_score = ? WHERE StudentID = ?",(python, English, ID))
	con += 1
	conn.commit()
print("Update data successfully..")
conn.close()

6.7 calculate_sum.py

import sqlite3
import random
conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
c = conn.cursor()
print("Opened databaase successfully..")
c.execute("SELECT StudentID, python_score, English_score from DK172")
marks = c.fetchall()
for mark in marks:
	total = mark[1] + mark[2]
	ID = mark[0]
	print(mark[1], mark[2], total)
	c.execute("UPDATE DK172 SET Total = ? WHERE StudentID = ?",(total, ID))
	conn.commit()
print("Calculate data successfully..")
conn.close()

6.8 show_data.py

import sqlite3
conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
c = conn.cursor()
print("Opened database successfully");
cursor = c.execute("SELECT StudentID, Name, python_score, English_score, Total  from DK172")
print("  StudentID   Name     python  English  Total")
for data in cursor:
	print(data[0], data[1], '\t', data[2],'\t', data[3],'\t', data[4])
print("Operation done successfully");
conn.close()

6.9 excel_test.py

from openpyxl import Workbook
import sqlite3
import random
wb = Workbook()
ws = wb.create_sheet("Mysheet",0)
conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
c = conn.cursor()
c.execute("SELECT * from DK172")
marks = c.fetchall()
head = ('StudentID', 'Name', 'Python_score', 'English_score', 'Total')
ws.append(head)
for mark in marks:
	print(mark[0], mark[1], mark[2], mark[3], mark[4])
	ws.append(mark)
conn.close()	
wb.save(r'C:\Users\ZHJ\Desktop\pywork\test.xlsx')

6.10 Final_procedure.py

import sqlite3
import random
from openpyxl import load_workbook, Workbook
def create_table():
	conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
	c = conn.cursor()
	print("Opened database successfully.")
	c.execute('''CREATE TABLE DK172 (StudentID, Name, python_score, English_score, Total score)''')
	conn.commit()
	print("Create table successfully!")
	conn.close()
	
def export_data():
	conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
	c = conn.cursor()
	#print("Opened databaase successfully..")
	print("Importing excel file......")
	wb = load_workbook(r'C:\Users\ZHJ\Desktop\pywork\DK172register.xlsx')
	ws = wb.worksheets[0]
	for row in ws.values:
		id = row[0]
		name = row[1]
		print(id, name, '\t', 'OK')
		c.execute("INSERT INTO DK172 (StudentID, Name) VALUES (%d, '%s')"%(int(id), name))
		conn.commit()
	print("Export data successfully!")
	conn.close()
	
def update_mark(AutoNum):
	global con
	conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
	c = conn.cursor()
	#print("Opened database successfully..")
	print("Then enter the marks.")
	c.execute("SELECT StudentID from DK172")
	IDs = c.fetchall()
	for id in IDs:
		ID = id[0]
		if con<AutoNum:
			python = random.randint(85, 100)
			English = random.randint(80, 100)
		else:
			if con == AutoNum:
				print("The first %d data have been randomly generated.\nplease manually enter the following data"%AutoNum)
			print("ID =",ID)
			python = int(input("Please type in the Python score:"))
			English = int(input("Please type in the English score:"))
		c.execute("UPDATE DK172 SET python_score = ?, English_score = ? WHERE StudentID = ?",(python, English, ID))
		con += 1
		conn.commit()
	print("Update data successfully!")
	conn.close()

def calculate_sum():
	conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
	c = conn.cursor()
	#print("Opened database successfully..")
	print("Calculate the total score...")
	c.execute("SELECT StudentID, python_score, English_score from DK172")
	marks = c.fetchall()
	for mark in marks:
		total = mark[1] + mark[2]
		ID = mark[0]
		#print(mark[1], mark[2], total)
		c.execute("UPDATE DK172 SET Total = ? WHERE StudentID = ?",(total, ID))
		conn.commit()
	print("Calculate data successfully!")
	conn.close()
	
def show_data():
	conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
	c = conn.cursor()
	#print("Opened database successfully")
	print("\n..............Show student data..............")
	cursor = c.execute("SELECT StudentID, Name, python_score, English_score, Total  from DK172")
	print("  StudentID   Name     python  English  Total")
	for data in cursor:
		print(data[0], data[1], '\t', data[2],'\t', data[3],'\t', data[4])
	print(".............   End of Table   .............")
	print("Operation done successfully");
	conn.close()

def export_to_excel():
	wb = Workbook()
	ws = wb.create_sheet("Mark",0)
	conn = sqlite3.connect(r'C:\Users\ZHJ\Desktop\pywork\class.db')
	c = conn.cursor()
	c.execute("SELECT * from DK172")
	marks = c.fetchall()
	head = ('StudentID', 'Name', 'Python_score', 'English_score', 'Total')
	print("Exporting to excel...")
	ws.append(head)
	for mark in marks:
		#print(mark[0], mark[1], mark[2], mark[3], mark[4])
		ws.append(mark)
	wb.save(r'C:\Users\ZHJ\Desktop\pywork\DK17-2_Mrak.xlsx')
	conn.close()
	print("Export excel successfully!")

if __name__ == '__main__':
	con = 0 
	create_table()
	export_data()
	update_mark(40)
	calculate_sum()
	show_data()
	export_to_excel()

6.11 order_data.py

import pandas as pd
df=pd.read_excel(r'C:\Users\ZHJ\Desktop\pywork\DK17-2_Mrak.xlsx',sheetname=0)
print(df.sort_index(by='Total', ascending=False))

6.12Final_procedure.py 效果展示

Python — 学生成绩管理_第25张图片

你可能感兴趣的:(实验报告)