本次实验要求使用python语言,读取现有的班级花名册,写入SQlite数据库,逐个显示每一个学生的学号姓名,输入其python、英语等课程的成绩,写入SQLite数据库。全部记录结束后,计算大家的总分、名次,并显示整个花名册。
在实验过程中,我首先分析实验要求,决定使用”将Excel文件导入数据库、录入学生各科成绩信息、计算总成绩、显示输出、导出文件”的基本思路,使用cmd和Notepad++环境进行实验。在”录入信息方式”,”输出显示方式”,”整合代码”,“导出为Excel文件”等方面进行代码优化,最终完成学生成绩管理程序的编写,完成实验要求。
关键字:Python SQLite数据库 文件读写 学生信息管理
读取现有的班级花名册,写入SQlite数据库,逐个显示每一个学生的学号姓名,输入其python、英语等课程的成绩,写入SQLite数据库。全部记录结束后,计算大家的总分、名次,并显示整个花名册。
首先需要创建一个数据库表格,用于储存学生的数据。之后,读出excel表中的数据,将数据插入到数据库表格中。然后手动或自动录入成绩信息。
读取数据库中各科成绩的信息,求和得出总成绩,将总成绩记录并更新表格。
将数据库表格中的数据,以一定的格式进行输出,并生成excel文件保存。
要读取excel文件,需要使用openpyxl模块,该模块是一个用于读取/写入Excel 2010 xlsx / xlsm / xltx / xltm文件的Python库。可以使用pip命令安装该模块。
在上图中,使用load_workbook()命令,打开了名为”DK172register.xlsx”的工作簿,使用.worksheet[0],选择第一张工作表。使用for语句对工作表内的数据循环输出。于是,程序就会将表格中的每行数据,以元组的形式输出。其中包括学号和姓名信息。
可以读取数据之后,我们需要创建一个数据库表格,用于储存读到的文件。
上图中,使用sqlite3模块,创建了一个名为”class.db”的数据库对象,之后,在数据库中创建了一个名为”DK172”的表格。该表格包含”StudentID、Name、python_score、English_score、Total”这几个表头,分别用来代表”学号、姓名、python成绩、英语成绩、总成绩”。
创建表格完成之后,我们就可以将excel中的数据导入到数据库中了。在这里,我也遇到了一些问题。
在上图中,我使用sqlite3模块创建数据库,使用openpyxl模块读取到了表格中的文件。将学号信息储存在id变量中,将姓名信息储存在name变量中。想通过INSERT语句及那个这两个信息插入到数据库表格中。没想到程序发生了错误。
在百度上查找相关资料,发现是INSERT语句的格式不对,经过修改后,再次执行程序:
上面的语句中,我将VALUES中的内容替换为了(%d ‘%s’),并用格式控制字符%将id、name变量中的值传入了VALUES中。程序正常执行,显示了导入数据的情况。为了更加直观的看出数据库中的数据,我使用”DB Brower for SQLite”查看数据库内容。
可以看出,数据已经成功地导入了数据库中。
在将excel表格中的数据导入到数据库之后,就需要插入成绩数据了。一开始我尝试使用INSERT语句进行数据导入,成绩数据导入成功,但是在DB中查看数据库,发现并不是我们想要的结果。
由上图可以看到,刚刚使用INSERT语句插入的随机成绩数据,并不是插入到了我们想要的位置,而是增加了新的数据。所以应该使用其他语句执行该命令。
于是,我尝试使用UPDATE命令,更新原有表格中的数据,从而实现添加数据的效果。
上图中,我首先使用SELECT语句将“DK172”表格中所有的“StudentID”数据取出,并保存在IDs中。接着,使用for语句,将”IDs”中的数据循环取出,使用UPDATE语句,对指定的学生ID进行更新操作。
可以看出,为了方便测试,程序中代表成绩的数据的”python”和”English”都是随机生成的。现在,我们去”DB Brower for SQLite”查看一下数据库里的内容。
可以看出,随机产生的”python”和”English”数据,已经成功插入到了数据库中指定的位置。现在,我尝试为数据库手动输入数据。
既然已经实现了将随机数据插入到数据库指定位置,要想实现手动输入数据,只需将产生随机数据改为手动输入数据就可以了。
将”python”和”English”更改为手动输入,就实现了手动输入数据的功能。但是,如果仅仅修改这些,我们班42人的所有数据都需要手动输入,比较麻烦。所以我希望实现”前40个数据随机产生,后2个数据手动输入”的功能。
要实现该功能,加一个条件判断语句就可以了,于是编写了下面的函数。
上图的函数,设置了一个变量”con”用来记录循环次数。当循环次数小于40次时,让数据随机产生;当循环次数大于40次时,显示提示并手动输入数据。
在上图中可以看出,最后两组数据确实是我所刚刚手动输入的数据。后面Total字段里的数据,我们可以先不看。那些数据是测试”计算总分”时产生的,与现在演示的功能无关。由于没有更新这些数据,所以这些数据是不正确的。
现在,已经实现了”导入Excel数据”和”录入分数”功能,下面将尝试进行”计算总成绩”。
要计算总分数,我想应该首先将每组数据中”python_score”和”English_score”数据取出,相加后记录在一个变量中,再使用UPDATE语句更新这组数据,从而将总分数据插入改组数据。于是编写如下代码:
上面的代码中,我首先使用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”表格。
可以看出,这里所显示的数据与图14所示的程序中的数据一致,说明程序执行成功。
现在就基本上实现了要求的功能,记录排序名次功能我没能实现,但已经可以实现简单的排序,我会在后面介绍。为了将数据库中的文件保存,我希望能将数据库中的文件导出为excel文件。
通过查阅资料和阅读课本例程,我编写了下面的代码去实现该功能。
上图的程序中,使用openpyxl模块用于对excel的操作,创建了一个名为“Mysheet“的工作表。连接到数据库之后,使用SELECT语句将”DK172“中的所有数据记录在marks变量中,定义一个名为”head”的元组数据,用于保存表头数据,使用.append()方法将marks中的所有数据全部导入到excel中,最后使用.save()方法,将excel文件保存并命名为”test.xlsx”,从而实现想要的功能。
上图中,可以看出已经将数据导入到了excel,但是字段为”StudentID”的那一列数据,显示的内容不对。查看其中任意一个元素的内容,可以在上方的内容栏看到该元素的内容。可以看出,我们刚刚导入的数据并没有问题,只是excel显示的数字格式不对。将其格式改为分数之后,内容就正常显示了。
接下来,我整理了之前写过的代码。将他们全部整合到了一个文件下,测试执行结果。由于代码稍多,我将它们拆分开进行分析。
上图定义了两个函数,”create_table()”用来创建一个数据库表格;”export_data()”用来导入花名册里的数据。
上图定义了两个函数,”update_mark()”用于录入数据,其中的”AutoNum”参数用来限定需要产生多少随机数据;“calculate_sum()”用来计算总成绩。
上图包含两个函数,”show_data()”用来在命令行显示数据;”export_to_excel()”用来将数据库中的文件导出生成excel表格。
上图是程序的调用部分,con是全局变量,用在”update_mark()”函数中。之后按顺序调用函数,分布实现想要的功能。
程序执行之后,首先会导入数据,它会先导入40组随机数据,然后让你输入两组数据。之后会计算总分,完成计算后,会将数据表格显示在命令行界面,最后,生成这些数据对应的excel文件。程序的执行效果还是不错的,但是由于显示的结果太长,我就不在这里截图演示了。我会在附录部分截图展示。
上面也曾说过,排名功能还没有实现。我曾尝试使用这样的思路:使用” ALTER”语句为数据库表格添加一个字段用于储存排名名次,之后使用SQLite的“Order By”子句,让所有数据根据总分降序排列,之后在新增的字段里按从1升序,写入名次,最后需要再次使用“Order By”按照”StudentID”升序排列。这样应该可以实现想要的效果,但是我卡在了”再新增字段里写入排名序号”这一步。因为我想使用UPDATE写入这些数据,但是UPDATE需要使用WHERE来描述更新数据的位置,然而经过排名的数据,“StudentID”已经乱序了,也就无法使用UPDATE语句。我也曾尝试使用索引方法,还是没有成功。
最后,我找到了pandas模块,但通过该模块,我目前也只能实现一个简单的排序功能。
上图中,使用pandas模块,先读取了刚刚生成的excel文件,然后使用.sort_index()方法对数据进行排序,其中的参数”by=Total“表示按照Total排序,”ascending=False”表示降序排列。
现在的程序中,包括导入数据和输入成绩数据等,都只是限制在了”特定格式的花名册”和”只有两科成绩”的条件内,可以在“增加程序适应性”方面加以改进。
现在我将代码集成在了一个文件中,但问题是:虽然不同的功能都定义了相应的函数,但是函数之间还是相互依赖,不够独立。以后可以优化代码,降低耦合性。
这次实验还是挺有意思的。编程过程中遇到了很多问题,最后通过查找资料等方法也都得到了解决。通过这次实验我也感受到,我在编程或者生活中遇到的问题,别人也有遇到,而他们会把解决方案放到网上与我们分享。所以说,网上的资源太多了。
但是,网上的资源大多也是提供一个解决方案,想真正能够深入学习,还是得静下心去慢慢学。
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)
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()
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()
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()
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()
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()
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()
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()
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')
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()
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))