Python项目:学生信息管理系统

Python学习笔记


课程笔记参考B站视频: Python全栈开发教程


第十六站 学生信息管理系统

1. 需求分析

学生管理系统应具备下面的功能:

  1. 添加学生及成绩信息。
  2. 将学生信息保存到文件中。
  3. 修改和删除学生信息。
  4. 查询学生信息。
  5. 根据学坐成绩进行排序。
  6. 统计学生的总分。

用户可以根据这个功能框架依次执行所有的功能。

2. 系统开发必备

系统开发环境:

操作系统:win10
Python解释器版本:Python3.8
开发工具:PyCharm
Python内置模块:os, re(正则表达式)

项目目录结构:

studentsys项目文件夹

students.txt 保存学生信息的文件(系统自动创建)
stusystem.py 实现具体功能的Python文件

3. 系统设计

于是根据上述系统的需求分析,将学生信息管理系统拆分为8大模块:

  1. 录入学生信息(会清除原来的信息)
  2. 查找学生信息
  3. 删除学生信息
  4. 修改学生信息(若ID不存在会自动添加)
  5. 对学生信息进行排序
  6. 统计学生总人数
  7. 显示所有学生信息
  8. 退出系统

整个系统的主函数业务流程如下:

要实现主函数的功能,方法如下:

编号功能
0退出系统
1录入学生信息,调用insert()自定义函数
2查找学生信息,调用search()自定义函数
3删除学生信息,调用delete()自定义函数
4修改学生信息,调用modify()自定义函数
5对学生成绩排序,调用sort()自定义函数
6统计学生总人数,调用total()自定义函数
7显示所有的学生信息,调用show()自定义函数

4. 学生信息维护模块设计

1. 录入学生信息功能
该模块要实现:从控制台录入学生信息,并且把它们保存到磁盘文件中,然后显示出来。业务流程如下:

2. 删除学生信息功能

该模块要实现:从控制台录入学生ID,到磁盘文件中找到对应的学生信息,并将其删除,然后显示当前所有学生信息。业务流程如下:

3. 修改学生信息功能

该模块要实现:从控制台录入学生ID,到磁盘文件中找到对应的学生信息,将其进行修改,然后显示当前所有学生信息。业务流程如下:

4. 查找学生信息功能

该模块要实现:从控制台录入学生ID或姓名,到磁盘文件中找到对应的学生信息,显示出来。业务流程如下:

5. 统计学生信息功能

该模块要实现:统计学生信息文件中保存的学生信息个数。业务流程如下:

6. 显示学生信息功能

该模块要实现:将学生信息文件中保存的全部学生信息获取并显示。业务流程如下:

7. 排序模块设计

该模块要实现:对学生信息按ID、姓名、C++成绩、Python成绩 、Java成绩、总成绩进行升序或降序排序,然后显示排序结果并写入到文件中。(都是按照Unicode的大小进行排序,使用函数ord()可以查看对应unicode值)

业务流程如下:

5. 项目打包

为了期望在其他计算机上运行该项目,在项目完成后需要进行打包。打包后,即使其他计算机没有安装Python环境,也可以运行这个exe文件。

想要进行打包,需要安装第三方模块PyInstaller。使用在线安装方式(具体的操作步骤可以参考第十四站 第五节),安装代码如下:

pip install PyInstaller

安装完成后执行语句:

pyinstaller -F py文件路径

-F表示只生成一个扩展名为.exe的可执行文件。执行后在倒数几行会看到生成的exe文件路径。

6. 实验感悟

  1. 这个实验的难点主要有两个:存储类型、排序。

1.1 存储类型
要明确:

  1. 字典列表是可以直接逐元素的写入到文本文件中的(会自动换行);
  2. 从文本文件中读取到的一切都是字符串列表,每个元素都代表一行;
  3. 处理数据的过程中都采用字典列表的方式,于是要想将字符串列表转换成字典列表,就需要逐元素的使用eval()函数。

1.2 排序
所有功能中最难实现的是排序功能,但是本项目中直接使用列表的.sort()排序方法,里面有专门针对字典列表的处理情况(使用了隐式函数):

stu_dir_lst.sort(key=lambda x:x['键名称'], reverse=True)
  1. 还有两点值得注意的问题:规范用户输入、理清逻辑框架。

2.1 规范用户输入
要想让用户输入几个有限的字符串,其实只要用一个while循环就可以轻松解决,学会了就可以一直用一个逻辑模板。比如下面代码示例:

# 询问用户是否继续
con_judge = input('请输入是否继续?y/n ')
while con_judge!='y' and con_judge!='Y' and con_judge!='n' and con_judge!='N':
   con_judge = input('输入错误!请输入是否继续?y/n ')
# 请用户输入整数/浮点数
while True:
   try:
       height = float(input('请输入您的身高(cm):'))
   except:
       print('输入有误!', end='')
   else:
       break

2.2 逻辑框架

感触比较深的一点是关于“总成绩”的键值对,后面有些模块会自动计算并保存到文件中,但是有些函数则不关心这个键值对。这主要是由于在一开始没有规划的太明白,好在最后配合起来(在用户端)也没啥问题。

所以最好是能在一开始搭建好基本模块框架后,就想好该使用什么函数完成各个模块,这样各部分数据在处理的过程中会更加丝滑。这种“写着写着功能就实现了”的思想不可取。(但是对我这种新手程序员来说,有时明知不对,那也得摁做😂)

最后,整个项目的源代码及可执行文件可以参考我的github仓库 Student-Info-Manager

7. 源码

没错,源码其实就在一个文件中,非常的简单!见下:

#Engineer: HuMu
#CreatTime: 2022/7/14 13:50
import os.path
stufile = 'students.txt'

def menu():
    print('学生信息管理系统'.center(57, '*'))
    print('功能菜单'.center(60, '-'))
    # print(' '.center(22), end='')
    print(' '.center(18), '1.录入学生信息(清除原有信息)')
    print(' '.center(18), '2.查找学生信息')
    print(' '.center(18), '3.删除学生信息')
    print(' '.center(18), '4.修改学生信息(ID不存在则自动添加)')
    print(' '.center(18), '5.对学生信息进行排序')
    print(' '.center(18), '6.统计学生总人数')
    print(' '.center(18), '7.显示所有学生信息')
    print(' '.center(18), '0.退出系统')
    print(''.center(63, '-'))

def save(lst_dir): # 将学生信息保存到文件中
    with open('students.txt', 'w', encoding='utf-8') as file:
        for i in lst_dir:
            # file.write('id:' + str(i['id']) + '\t')
            # file.write('name:' + str(i['姓名']) + '\t')
            # file.write('C++成绩:' + str(i['C++成绩']) + '\t')
            # file.write('Python成绩:' + str(i['Python成绩']) + '\t')
            # file.write('Java成绩:' + str(i['Java成绩']) + '\t')
            # file.write('\n')
            file.write(str(i) + '\n')

def insert(): # 录入学生信息
    stu = []
    while True:
        # 输入学生的信息
        id_num = input('请输入学生学号:')
        while not id_num:
            print('输入错误,请重新输入学生学号:')
            id_num = input('请输入学生学号:')
        # 防止出现学号相同的情况
        id_exist = False
        for i in stu:
            if i['id']==id_num:
                id_exist = True
        if id_exist:
            print('该ID的学生信息已录入,请输入其他ID')
            continue
        name = input('请输入学生姓名:')
        while not name:
            print('输入错误,请重新输入学生姓名')
            name = input('请输入学生姓名:')
        score1 = input('请输入C++成绩:')
        while not score1.isdecimal():
            score1 = input('输入错误,请重新输入C++成绩:')
        score1 = int(score1)
        score2 = input('请输入Python成绩:')
        while not score2.isdecimal():
            score2 = input('输入错误,请重新输入Python成绩:')
        score2 = int(score2)
        score3 = input('请输入Java成绩:')
        while not score3.isdecimal():
            score3 = input('输入错误,请重新输入Java成绩:')
        score3 = int(score3)

        # 将学生的信息放到字典中
        stu.append({'id':id_num, '姓名':name, 'C++成绩':score1, 'Python成绩':score2, 'Java成绩':score3})

        # 判断是否继续录入信息
        judge = input('是否继续录入信息?y/n ')
        while judge!='y' and judge!='Y' and judge!='n' and judge!='N':
            judge = input('是否继续录入信息?y/n ')
        if judge=='n' or judge=='N':
            break
        else:
            continue

    # 保存学生信息到文本文件当中
    save(stu)
    print('学生信息录入完毕!!!')

def serach(): # 查找学生信息
    if os.path.exists(stufile):
        while True:
            # 读取学生信息,并将其转化成字典列表
            stu_dir = []
            with open(stufile, 'r', encoding='utf-8') as rfile:
                stu_str = rfile.readlines()
            for i in stu_str:
                stu_dir.append(eval(i))

            # 用户输入查找模式
            ser_mode = input('按ID查找请输入1,按姓名查找请输入2:')
            while ser_mode!='1' and ser_mode!='2':
                ser_mode = input('输入错误!按ID查找请输入1,按姓名查找请输入2:')

            # 用户输入查找内容
            if ser_mode=='1':
                ser_info = input('请输入要查找的ID:')
                while not ser_info:
                    ser_info = input('输入无效!请输入要查找的ID:')
            else:
                ser_info = input('请输入要查找的姓名:')
                while not ser_info:
                    ser_info = input('输入无效!请输入要查找的姓名:')

            # 查找信息
            stu_res = [] # 查找的结果
            find_flag = False
            if ser_mode=='1':
                for i in stu_dir:
                    if i['id']==ser_info:
                        stu_res.append(i)
                        find_flag = True
            else:
                for i in stu_dir:
                    if i['姓名']==ser_info:
                        stu_res.append(i)
                        find_flag = True
            if not find_flag:
                print('您输入的信息未查询到!')
            else:
                print('您输入的信息已查到!')

            # 展示查询到的信息
            format_title = '{:^6}\t{:^6}\t{:^10}\t{:^10}\t{:^10}\t{:^10}'
            print(format_title.format('ID', '姓名', 'C++成绩', 'Python成绩', 'Java成绩', '总成绩'))
            for i in stu_res:
                print(format_title.format(i['id'], i['姓名'],
                      i['C++成绩'], i['Python成绩'], i['Java成绩'],
                      i['C++成绩']+i['Python成绩']+i['Java成绩']))

            # 询问是否继续
            con_flag = input('是否继续查询?y/n ')
            while con_flag!='y' and con_flag!='Y' and con_flag!='n' and con_flag!='N':
                con_flag = input('输入错误!是否继续查询?y/n ')
            if con_flag=='y' or con_flag=='Y':
                continue
            else:
                break
    else:
        print('还未保存过学生信息!!')
        return

def delete(): # 删除学生信息
    while True:
        id_num = input('请输入要删除的学生的ID:')
        while not id_num:
            print('ID输入格式错误,请重新输入:')
            id_num = input('请输入要删除的学生的ID:')

        # 读取文件中的内容
        if os.path.exists(stufile):
            with open(stufile, 'r', encoding='utf-8') as rfile:
                student_old = rfile.readlines()
        else:
            print('暂未保存过数据!!')
            return

        # 将不删除的信息重新覆盖写入文件
        find_id = False
        if student_old:
            with open(stufile, 'w', encoding='utf-8') as wfile:
                for i in student_old:
                    sing_stu = eval(i)
                    if sing_stu['id']!=id_num:
                        wfile.write(i) # 将字符串转换成字典
                    else:
                        find_id = True
        else:
            print('学生信息为空!')
            return

        # 显示是否删除
        if find_id:
            print('ID为{0}的学生信息已删除!'.format(id_num))
        else:
            print('未找到ID为{0}的学生信息!'.format(id_num))

        # 重新显示所有学生信息
        show()

        # 询问是否要继续删除
        conti_del = input('是否继续删除学生信息?y/n ')
        while conti_del!='y' and conti_del!='Y' and conti_del!='N' and conti_del!='n':
            conti_del = input('输入错误,是否继续删除学生信息?y/n ')
        if conti_del=='y' or conti_del=='Y':
            continue
        else:
            break
    return

def modify(): # 修改学生信息
    stu_dir = []
    while True:
        # 判断文件是否存在
        if os.path.exists(stufile):
            # 读取文件全部信息
            with open(stufile, 'r', encoding='utf-8') as rfile:
                stu_lst = rfile.readlines()
            for i in stu_lst:  # 将列表内的字符串元素转化成字典元素
                stu_dir.append(eval(i))

            # 用户输入学生信息
            id_num = input('请输入学生学号:')
            while not id_num:
                print('输入错误,请重新输入学生学号:')
                id_num = input('请输入学生学号:')
            name = input('请输入学生姓名:')
            while not name:
                print('输入错误,请重新输入学生姓名')
                name = input('请输入学生姓名:')
            score1 = input('请输入C++成绩:')
            while not score1.isdecimal():
                score1 = input('输入错误,请重新输入C++成绩:')
            score1 = int(score1)
            score2 = input('请输入Python成绩:')
            while not score2.isdecimal():
                score2 = input('输入错误,请重新输入Python成绩:')
            score2 = int(score2)
            score3 = input('请输入Java成绩:')
            while not score3.isdecimal():
                score3 = input('输入错误,请重新输入Java成绩:')
            score3 = int(score3)

            # 判断学生ID是否存在,不存在就添加
            id_exist = False
            for i in stu_dir:
                if i['id']==id_num:
                    id_exist = True
                    stu_dir.remove(i)
                    stu_dir.append({'id':id_num, '姓名':name, 'C++成绩':score1, 'Python成绩':score2, 'Java成绩':score3})
            if not id_exist:
                stu_dir.append({'id':id_num, '姓名':name, 'C++成绩':score1, 'Python成绩':score2, 'Java成绩':score3})

            # 保存学生信息
            save(stu_dir)

            # 显示学生信息
            show()

            # 询问是否继续
            con_judge = input('是否继续修改学生信息?y/n ')
            while con_judge!='Y' and con_judge!='y' and con_judge!='N' and con_judge!='n':
                con_judge = input('输入错误!是否继续修改学生信息?y/n ')
            if con_judge=='Y' or con_judge=='y':
                continue
            else:
                break # 当然return也行
        else:
            print('学生信息文件不存在!')
            break

def sort():   # 排序
    show()
    if os.path.exists(stufile):
        while True:
            # 读取全部信息并转换成字典列表
            stu_lst = []
            with open(stufile, 'r', encoding='utf-8') as rfile:
                stu_lst = rfile.readlines()
            if not stu_lst:
                print('还未录入学生信息!!')
                return
            else:
                stu_dir = []
                for i in stu_lst:
                    stu_dir.append(eval(i))

            # 计算每个学生的总成绩
            stu_dir_whole = []
            for i in stu_dir:
                i['总成绩']=i['C++成绩'] + i['Python成绩'] + i['Java成绩']
                stu_dir_whole.append(i)

            # 用户选择排序类型及排序方式
            sort_tip = '排序依据提示'.center(12,'-') + \
                       '\n1.按ID排序\n' \
                       '2.按姓名排序\n' \
                       '3.按C++成绩排序\n' \
                       '4.按Python成绩排序\n' \
                       '5.按Java成绩排序\n' \
                       '6.按总成绩排序\n' + \
                       ''.center(16, '-') + \
                       '\n请输入排序依据:'
            sort_col = input(sort_tip)
            while sort_col not in['1','2','3','4','5','6']:
                  sort_col = input('输入错误!\n' + sort_tip)
            sort_mode = input('升序排序请输入1,降序排序请输入2:')
            while sort_mode!='1' and sort_mode!='2':
                sort_mode = input('输入错误!升序排序请输入1,降序排序请输入2:')

            # 进行排序操作
            if sort_col=='1':
                stu_dir_whole.sort(key=lambda x: x['id'], reverse=sort_mode=='2')
            elif sort_col=='2':
                stu_dir_whole.sort(key=lambda x: x['姓名'], reverse=sort_mode=='2')
            elif sort_col=='3':
                stu_dir_whole.sort(key=lambda x: x['C++成绩'], reverse=sort_mode == '2')
            elif sort_col=='4':
                stu_dir_whole.sort(key=lambda x: x['Python成绩'], reverse=sort_mode=='2')
            elif sort_col=='5':
                stu_dir_whole.sort(key=lambda x: x['Java成绩'], reverse=sort_mode=='2')
            elif sort_col=='6':
                stu_dir_whole.sort(key=lambda x: x['总成绩'], reverse=sort_mode=='2')
            else:
                print('出现了未能预知的错误!重启吧')
                return

            # 保存信息并展示
            save(stu_dir_whole)
            print('排序结果为:')
            show()

            # 询问是否继续排序
            con_flag = input('是否继续排序?y/n ')
            while con_flag!='n' and con_flag!='N' and con_flag!='y' and con_flag!='Y':
                con_flag = input('输入错误!是否继续排序?y/n ')
            if con_flag=='y' or con_flag=='Y':
                continue
            else:
                return
    else:
        print('还未录入学生信息!!')
        return

def total():  # 统计学生总人数
    if os.path.exists(stufile):
        # 读取学生信息
        with open(stufile, 'r', encoding='utf-8') as rfile:
            stu_lst = rfile.readlines()

        # 输出统计结果
        stu_num = len(stu_lst)
        if stu_num==0:
            print('还未录入学生信息!!')
        else:
            print('学生总人数为 {}'.format(stu_num))
    else:
        print('还未录入学生信息!!')
        return

def show():   # 显示所有学生信息
    if os.path.exists(stufile):
        # 读取所有信息
        stu_lst = []
        with open(stufile, 'r', encoding='utf-8') as rfile:
            stu_lst = rfile.readlines()

        # 将读取的信息转化成字典列表并打印显示
        if stu_lst:
            stu_dir = []
            for i in stu_lst:
                stu_dir.append(eval(i))

            print('以下为所有的学生信息:')
            format_title = '{:^6}\t{:^6}\t{:^10}\t{:^10}\t{:^10}\t{:^10}'
            print(format_title.format('ID', '姓名', 'C++成绩', 'Python成绩', 'Java成绩', '总成绩'))
            for i in stu_dir:
                print(format_title.format(i['id'],
                                          i['姓名'],
                                          i['C++成绩'],
                                          i['Python成绩'],
                                          i['Java成绩'],
                                          i['C++成绩'] + i['Python成绩'] + i['Java成绩']))
            print('所有学生信息显示完毕!!')
            return
        else:
            print('还未录入学生信息!!')
            return
    else:
        print('还未保存学生信息!!')
        return

def main():
    while True:
        menu()
        while True:
            choice = input('请选择功能序号:')
            if choice.isdecimal():
                choice = int(choice)
                if choice in [0, 1, 2, 3, 4, 5, 6, 7]:
                    break
                else:
                    continue
            else:
                continue
        if choice == 0:
            answer = input('您确定要退出系统吗?y/n ')
            if answer=='y' or answer=='Y':
                print('感谢您的使用!!')
                break
            else:
                continue
        elif choice == 1:
            insert() # 录入学生信息
        elif choice == 2:
            serach() # 查找学生信息
        elif choice == 3:
            delete() # 删除学生信息
        elif choice == 4:
            modify() # 修改学生信息
        elif choice == 5:
            sort()   # 排序
        elif choice == 6:
            total()  # 统计学生总人数
        elif choice == 7:
            show()   # 显示所有学生信息

if __name__ == '__main__':
    main()
  • 14
    点赞
  • 129
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虎慕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值