【软件实践 1】 小程序的测试与修改
🚀【软件实践 1】小程序的测试与修改
- 项目介绍
- 修改方案
- 代码实现
- 运行截图
- 实验总结
- 参考资料
项目介绍
项目名称:基于Python的课堂点名器
项目来源:博客来源链接 https://blog.csdn.net/qq_45405176/article/details/105004692
项目概要:用Python实现一个简单课堂点名器
- 以某班级学生名单为例,从外部文件导入学生信息,随机对班级所有同学进行点名;
- 判断未到学生是否有请假条,有则视为请假,无则视为旷课。
- 对点名结束后进入教室的学生将旷课改为迟到。
- 对中途离开课堂学生计为早退(需要考虑学生既是迟到又是早退的情况)。
- 按照请假、旷课、迟到、早退四类分别展示。
- 将未到学生按照请假、旷课、迟到、早退四类分别存储在四个.csv格式的文件中。
原项目部分源代码如下 (源码较长,完整代码请点击链接查看原文):
1 import xlrd #导入xlrd包,对Excel读取数据
2 import pandas as pd #导入pandas包,用于对Excel操作
3 import random
4
5 #定义函数:从Excel文件读取学号和姓名,返回全体学号和姓名列表
6 def student(address):
7 data = xlrd.open_workbook(address)
8 table = data.sheet_by_name('Sheet1') #选定页码1--(Sheet1).
9
10 rowNum = table.nrows #总行数
11 colNum = table.ncols #总列数
12 a = [] # 获得学号
13 b = [] # 获得姓名
14
15 for y in range(colNum): #自动索引学号(xuehao),姓名(name)
16 if table.cell_value(0, y) == 'xuehao':
17 for x in range(1, rowNum):
18 vaule = table.cell_value(x, y)
19 vaule = float(vaule)
20 vaule = int(vaule)
21 a.append(vaule)
22
23 if table.cell_value(0, y) == 'name':
24 for x in range(1, rowNum):
25 vaule = table.cell_value(x, y)
26 b.append(vaule)
27 return a, b
28
29 ......
30 ......
31
32 #定义函数:输入列表学号,姓名,得到table表中date数据
33 def date(a,b):
34 students = dict(zip(a, b))
35 d = []
36 for c in a:
37 e = []
38 e.append(c)
39 e.append(students[c])
40 d.append(e)
41 return d
42
43 #主函数
44 address = r'D:\mingdan.xls'
45 x = student(address)
46 a = x[0]
47 b = x[1]
48 print('请输入本班要点名的人数(全班人数:{0}):'.format(len(a)),end='')
49 num1 = num()
50 x = dianming(a, b, num1)
51 c = x[0]
52 d = x[1]
53 x = panduan1(c,d)
54 e = x[0] #早退1
55 f = x[1]
56 g = x[2]
57 h = x[3]
58 x = qingjia(g,h)
59 i = x[0] #早退2
60 j = x[1]
61 k = e + i
62 l = f + j
63 m = []
64 for i in k:
65 hao = 'id'+str(i)
66 m.append(hao)
67 o = date(m,l)
68 table('早退学号','早退姓名',o,'D:/zaotui.csv')
源程序分析
- 经过分析,源程序的逻辑如图:
图为手写简略分析图
- 由于定名方式是随机点名,所以导入random模块;
- 想要从外部文件读取学生名单,这里用到xlrd包;
- 想要将请假…等四类名单分别存储在四个.csv格式的文件中。
- 这里采用pandas包,用于对excel的操作。
图为需要提前导入的包和模块
- 外部文件为Excel格式,从D盘读取名单。原名单保存为xls格式,不知道为什么保存为xlsx.模式无法运行程序。
- 后来查了一下,因为我的python版本下的是python3,不支持xlsx文档格式。
图为创建的”mingdan.xls“文件
图为创建的”mingdan.xls“名单
- 由于学号过长时,显示为科学计数的方式,这里将学号转化为字符,前面加上id,采用 id+学号 的格式;
- 注意test.to_csv(address, encoding=“gbk”),这样可以保证csv文件中文不是乱码
- 由于要对学生点名,这里采用学号索引,用了大量的函数模块,利用函数来返回学号和姓名,通过函数来实现不同的功能:
- 按照函数顺序依次进行点名流程;
图为运行截图
- 图一内红点标出的是新生成的文件。图二为打开新生成的文件后显示的名单,名单仅在xlsx文档内显示而不在运行界面上显示。
以上就是原程序大致分析,经过总结,原程序需要实现的主要功能是后面修改程序时仍需要保留的功能,基于以下几个基本功能:
- 读取名单
- 产生随机点名名单
- 点名并输出特定学生名单
- 将特定名单写入表格存档
修改方案
- 仍需要保留原程序的四个基本功能,在此基础上对原程序进行修改。
- 将原项目中的xlsx.文件转化成csv.文件后再进行处理,因为csv中的open()/reader()等函数可以更方便的读取和写入数据。然后通过项目1的思路(这里不再赘述),达到项目2的目的。
- 直接将迟到/未到/已到的学生显示在交互界面,并且也会录入xlsx.表格中,这些同学的信息会被输出且导入到新的csv文件中。
- 在点名环节新增了捕获异常的功能。用于处理不按要求签到的用户,单独定义了一个list,并对这些同学单独进行一次点名,将再次输入错误的学生导入“未到学生名单”中;
- 点名环节不但会捕获异常,并且还会将连续两次输入错入的学生加入旷课名单中。点名环节需要处理不按要求输入的用户,可以单独定义一个list,然后最后再进行点名;若同一个学生答道再次输入错误,该同学将会被导入未到学生名单。
- 根据以上初步想法,可拟出修改后程序的大致功能:
- 读入csv文件学生名单
- 产生随机学生名单
- 完成点名器的初始化
- 点名
- 写入csv文件,输出未到名单
- 输出传入的特定列表数据
- 主函数
代码实现
- 根据以上修改目标,修改后完整代码如下
1 ''' @信息学院软工1--【软件工程综合实践1】 '''
2
3 import csv
4 import random
5
6
7 # 功能:读入csv文件学生名单
8 # 输入:文件名
9 # 返回值:学生名单(list),学生全部信息(dict)
10 def file_in(file_name):
11 students_info = {}
12 students_name = []
13 with open(file_name, newline='') as info:
14 reader = csv.reader(info)
15 for row in reader:
16 students_info[row[0]] = row[1]
17 students_name.append(row[0])
18 return students_info, students_name
19
20
21 # 功能:产生随机学生名单
22 # 输入:学生名单(list)
23 # 返回值:打乱的学生名单(list)
24 def new_list(students_name):
25 student_upset_name = random.sample(students_name, len(students_name))
26 return student_upset_name
27
28
29 # 功能:完成点名器的初始化
30 # 输入:学生名单(list)
31 # 返回值:学生信息(dict)和打乱的学生名单(list)
32 def dmq_init(file_name):
33 student_info = file_in(file_name)[0]
34 # print(students_wg_dict)
35 student_upset_name = new_list(file_in(file_name)[1])
36 # print(students_wg_list)
37 return student_info, student_upset_name
38
39
40 # 功能:点名
41 # 输入:打乱的学生名单(list)
42 # 返回值:未到学生名单(list)
43 def dmq_dm(student_upset_name):
44 student_late = []
45 student_dm_wrong = []
46 for name in student_upset_name:
47 temp = input(name + "到了吗?(是:1,否:2)")
48 if temp == "1":
49 continue
50 elif temp == "2":
51 student_late.append(name)
52 else:
53 student_dm_wrong.append(name)
54 print("请按要求输入!该名字被放置最后点名。")
55 if student_dm_wrong:
56 for name in student_dm_wrong:
57 temp = input(name + "到了吗?(是:1,否:2)")
58 if temp == "1":
59 continue
60 elif temp == "2":
61 student_late.append(name)
62 else:
63 print("仍然未按照要求输入!算入未到名单!")
64 student_late.append(name)
65 return student_late
66
67
68 # 功能:写入csv文件,输出未到名单
69 # 输入:未到学生名单(list)和学生全部信息(dict)
70 # 返回值:无
71 def dmq_file_in(students_late, student_info, num):
72 students_late_info = []
73 for name in students_late:
74 students_late_info.append([name, student_info[name]])
75 print_info(students_late_info, num)
76 with open("late_students_info.csv", "w", newline="") as file_in:
77 file_writer = csv.writer(file_in, quotechar='|', quoting=csv.QUOTE_MINIMAL)
78 for info in students_late_info:
79 file_writer.writerow(info)
80 print("\n已导出未到学生名单!文件位置位于当前目录下late_students_info.csv")
81
82
83 # 功能:输出传入的 特定 列表数据
84 # 输入:特定的list [[*, *], [*, *], [*, *], ...]
85 # 返回值:无
86 def print_info(special_list, num):
87 count = 0
88 print("未到名单如下("+str(num)+"个一行):")
89 for i in special_list:
90 if (count % num == 0) & (count != 0):
91 print()
92 print(i[0]+","+i[1], end=' ')
93 count += 1
94 # 主函数
95 def main(file_name):
96 # 5代表5个名字一行输出
97 dmq_file_in(dmq_dm(dmq_init(file_name)[1]), dmq_init(file_name)[0], 5)
98 main("D:/mingdan.csv")
- 修改后的程序加入了更多错误处理机制,对点名时输入错误进行了进一步的判断和处理,减少了点名时的干扰因素。同时将名单更直接地输出在运行框内,更方便直观地展示了点名信息。
- 修改后的程序与原程序最大的区别就是创建了更多的函数,将各个功能模块分开了,降低了各个功能之间的耦合程度,这样在后期需要加入更多功能时更容易修改和完善代码,在代码层面上实现了改善;。
- 特别说明:本修改程序由于时间和任务量限制,没有和原程序一样将学生分为迟到、缺勤、早退等类别,仅实现了记录了未到学生。但是,其它分类的操作可以套用本程序的函数进行实现。
运行截图
- 先在D盘中创建一个学生名单(保存为csv格式(显示为xls))
- 以下选中的文件是新创建"mingdan.csv"文件,注意与源程序同名文件区别(源文件为xls格式)。
- 其它文件均为原程序创建的文件,与修改后程序无关。
- 我将信息学院部分学生的信息导入了,用学号索引。
- 在python中导入csv模块(若没有就打开cmd,使用pip命令下载csv)
- 用random函数实现乱序点名功能
图为需要导入的模块和包
- 这是第一次输入错误,程序会要求重新输入一次,再次输入错误将被加入到未到名单中。
- 这是第二次输入,程序会将连续两次输入错误的名单输出到未到学生名单里。与原程序不同的是,原程序不会将未到名单直接打印出来,只能通过打开excel文件才能看到名单。
- 通过标红的可以看出,程序已将连续两次输入错误的学生名单加入了未到学生名单中。
- 最后程序会导出未到学生名单,生成一个新的csv文件到py文件源目录下。
- 这是新生成的文件。储存在源文件文件夹目录中。
实验总结
-
虽然比原程序优化了很多,但是总觉得好像哪里还能优化,但是因为自己技术有限暂时还没想出更好的方法。不过已经基本完成了想要改进的目标。以后学习了新的excel处理方法和技术再继续优化。
-
不知道为什么一开始我创建了一个
xlsx
文件程序一直无法运行,说是不支持xlsx
文件格式,难道是因为我的py版本问题吗。后来创建了xls
文件后就可以运行了。(更新:python3不支持xlsx格式) -
test.to_csv(address, encoding=“gbk”)
,这样可以保证csv文件中文不是乱码 -
为了防止学号过长时,显示为科学计数的方式,这里将学号转化为字符,前面加上id,采用 id+学号 的格式
-
random
和csv
两个模块,random
模块是为了实现随机点名,只用到了sample()
;csv模块用到了reader()
和writer()
,搭配open(
)函数完成文件读入写出。 -
csv是文本文件,用记事本就能打开,XLS是二进bai的文件只有用EXCEL才能打开, csv文件是以逗号为分隔符号,将各字段列分离出的一种ASCII文件;
-
xls 是一个特有的二进bai制格式,其核心结构是复合文档类型的结构,而 xlsx 的核心结构是 XML 类型的结构,采用的是基于 XML 的压缩方式,使其占用的空间更小。