一个简单的多用户交互系统的实现
Posted 江湖乄夜雨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个简单的多用户交互系统的实现相关的知识,希望对你有一定的参考价值。
需求如下:创建管理员、教师、学员这三个视图,实现一个简单的课程操作交互
具体实现如下:
Homework:
│
├─bin
│──────start.py #程序的入口
│
├─conf
│──────config.py #程序用到的文件的路径以及其他关系映射信息
│
├─core #
│──────logger.py#记录日志的逻辑
│──────main.py#实现三类用户的登陆逻辑,并利用反射调用不同类的具体方法
│──────manager.py#实现了管理员类的各个功能
│──────my_pickle.py#实现了将不同对象dump、load进文件的方法以及修改已经被dump的文件的方法
│──────other_logics.py#其他额外功能的逻辑
│──────school.py#里面的classes类用来创建与班级名相同名字的文件
│──────student.py#实现学生类的功能逻辑
│──────teacher.py#实现讲师类的功能逻辑
│
└─db
│──classes_obj#存放各个班级对象的信息
│──logs.log#存放日志信息
│──teacher_obj#存放讲师对象信息
│──userinfo#存放登陆用户信息
│
└─studentinfo#里面的文件是与班级同名的文件,各个文件里面存的是相应班级里的学员信息
│────────python_s9
代码如下:
from os import getcwd,path from sys import path as sys_path sys_path.insert(0,path.dirname(getcwd())) from core import main if __name__ == \'__main__\': main.main()
import os PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #userinfo文件的路径 USERINFO = os.path.join(PATH,\'db\',\'userinfo\') #schoolinfo的路径 SCHOOLINFO = os.path.join(PATH,\'db\',\'school_obj\') #teacher_obj的路径 TEACHER_OBJ = os.path.join(PATH,\'db\',\'teacher_obj\') #classes_obj的路径 CLASSES_OBJ = os.path.join(PATH,\'db\',\'classes_obj\') #course_obj的路径 COURSE_OBJ = os.path.join(PATH,\'db\',\'course_obj\') #studentinfo的路径 STUDENTINFO = os.path.join(PATH,\'db\',\'studentinfo\') #日志文件的路径 LOGGER = os.path.join(PATH,\'db\',\'logs.log\') #用户选择视图输入项与身份信息的键值对 USER_DICT = {\'1\':\'Manager\',\'2\':\'Teacher\',\'3\':\'Student\'} #学校与课程对应关系字典 school_class = {\'Beijing\':[\'python\',\'linux\'],\'Shanghai\':[\'go\']}
import logging from conf import config def logger_file(): #生成logger对象 whw_logger = logging.getLogger(\'logs.log\') whw_logger.setLevel(logging.INFO) #生成handler对象 whw_fh = logging.FileHandler(config.LOGGER) whw_fh.setLevel(logging.INFO) #生成Formatter对象 file_formatter = logging.Formatter(\' %(asctime)s - %(name)s - %(levelname)s - %(message)s \') #把formatter对象绑定到handler对象中 whw_fh.setFormatter(file_formatter) # 把handler对象绑定到logger对象中 whw_logger.addHandler(whw_fh) return whw_logger def write_log(msg): log_obj = logger_file() log_obj.info(msg) log_obj.handlers.pop()
import sys import os from core.manager import Manager from core.teacher import Teacher from core.student import Student from conf import config from core import my_pickle from .other_logics import file_name,show_classes,show_student_score def login(): \'\'\' 登录函数,应该先到conf.config中先读取userinfo的文件路径。 再读取userinfo文件中的信息,对用户名与密码进行查验 登陆成功后查看这个人的身份来确定进入哪一个视图 :return: \'\'\' while 1: print( \'\\033[1;32m请选择用户视图:\\n\\033[0m\', \'1:管理员视图\\n\', \'2:讲师视图\\n\', \'3:学生视图\\n\' ) choice = input(\'请选择相应视图的编号:\') if not choice.isdigit() or int(choice)<=0 or int(choice)>3: print(\'\\033[1;31m请输入正确的编号!\\033[0m\') continue else: username = input(\'用户名:\') password = input(\'密 码:\') user_identity = config.USER_DICT[choice] #打开userinfo文件... with open(config.USERINFO,\'r\',encoding=\'utf-8\') as f: for line in f: user_name,pass_word,identity = line.strip().split(\'|\') #必须是用户名 密码 身份 三个全部一致才能登陆成功 if user_name == username and password == pass_word and user_identity == identity: print(\'\\033[1;32m%s 用户 %s 登陆成功!\\033[0m\' % (user_identity,username)) #以字典形式返回用户名 身份 return {\'username\':username,\'identity\':identity} else: print(\'\\033[1;31m抱歉,输入有误,登陆失败!\\033[0m\') def main(): \'\'\' 打印欢迎信息 调用login()——得到一个返回值:用户的姓名与身份 打印用户身份的功能菜单 如果用户想要调用任何方法,应该通过角色的对象调用,跳转到对应对象的方法里 :return: \'\'\' print(\'\\033[0;35m欢迎进入学生选课系统!\\033[0m\') ret = login() if ret: while 1: #管理员登陆 if ret[\'identity\'] == \'Manager\': print(\'\\033[0;32m******************\\033[0m\') role_class = getattr(sys.modules[__name__],ret[\'identity\']) #将类实例化成相应的对象 obj = role_class(ret[\'username\']) while 1: print(\'\\033[0;32m******************\\033[0m\') for i,v in enumerate(role_class.menu,1): print(i,v[0]) #避免输入不合法,利用异常处理 choice = input(\'\\033[0;32m请输入您要进行的操作编号:\\033[0m\') if not choice.isdigit(): print(\'\\033[1;31m请输入数字!\\033[0m\') break choice_int = int(choice) if choice_int < 1 or choice_int > 9: print(\'\\033[1;31m抱歉,请输入正确的编号!\\033[0m\') break ##进行第二次的反射,后面加了括号直接执行了 getattr(obj,role_class.menu[choice_int-1][1])() #讲师登陆 if ret[\'identity\'] == \'Teacher\': print(\'\\033[0;32m******************\\033[0m\') global teacher_school #反射:从本模块找到Teacher类 teacher_class = getattr(sys.modules[__name__],ret[\'identity\']) pk_teacher = my_pickle.MyPickle(config.TEACHER_OBJ) ob_teacher = pk_teacher.loaditer() for i in ob_teacher: if i.name == ret[\'username\']: teacher_school = i.school #利用找到的Teacher类与用户输入的name、school实例化讲师对象 teacher_obj = teacher_class(ret[\'username\'],teacher_school) while 1: print(\'\\033[0;32m******************\\033[0m\') for i,v in enumerate(teacher_class.menu,1): print(i,v[0]) choice = input(\'\\033[0;32m请输入您要进行的操作编号:\\033[0m\') if choice.isdigit() and 0 < int(choice) < 5: choice_int = int(choice) #第二次反射,后面加了括号,直接执行就行 getattr(teacher_obj,teacher_class.menu[choice_int-1][1])() else: print(\'\\033[1;31m抱歉,请输入正确的编号!\\033[0m\') #学生登录——需要输入班级 if ret[\'identity\'] == \'Student\': global stu_status stu_status = False global stu_class print(\'\\033[0;32m******************\\033[0m\') class_input = input(\'请输入您所在的班级:\').strip() #判断输入的班级是否存在 if class_input not in file_name(config.STUDENTINFO): print(\'\\033[1;31m抱歉,请输入正确的班级!\\033[0m\') else: #判断输入的班级有没有登陆的学生name pk_student = my_pickle.MyPickle(os.path.join(config.STUDENTINFO,class_input)) obj_student = pk_student.loaditer() for i in obj_student: #找到了这个学生对象 if i.name == ret[\'username\']: #将这个班级赋值给global变量stu_class stu_class = i.clas stu_status = True #说明成功找到了该学生的对象 if stu_status == True: # 第一次反射 student_class = getattr(sys.modules[__name__], ret[\'identity\']) #实例化 student_obj = student_class(ret[\'username\'],stu_class) while 1: print(\'\\033[0;32m******************\\033[0m\') for i,v in enumerate(student_obj.menu,1): print(i,v[0]) choice = input(\'请输入您要进行的操作编号:\') if choice.isdigit() and ( 0 < int(choice) < 3): if choice == \'1\': show_student_score(ret[\'username\'],class_input) elif choice == \'2\': exit() else: print(\'\\033[1;31m请输入正确的操作编号!\\033[0m\') else: print(\'\\033[1;31m抱歉您不在这个班级!\\033[0m\') else: print(\'\\033[1;31m请输入正确的用户编号\\033[0m\')
#首先,以管理员的身份登录 #登录后 应该实例化一个对应身份的对象manager_obj = manager(name) #管理员对象可以调用所有的方法 from conf import config from core import teacher from core import my_pickle from core import student from core import school from .other_logics import file_name from .logger import logger_file from .logger import write_log import os #管理员类 class Manager: menu =[ (\'创建讲师账号\',\'create_teacher\'),(\'创建学生账号\',\'create_student\'), (\'创建班级\', \'create_classes\'), (\'查看学校\',\'show_school\'), (\'查看课程\',\'show_courses\'),(\'查看讲师\',\'show_teachers\'), (\'查看班级\',\'show_classes\'),(\'为班级指定老师\',\'bound_class_teacher\'), (\'退出\',\'exit\') ] def __init__(self,name): self.name = name #相当于拿到了一个对象,这个对象里面只存了文件的名字 self.teacher_pickle_obj = my_pickle.MyPickle(config.TEACHER_OBJ) #拿到 mypickle_obj self.school_pickle_obj = my_pickle.MyPickle(config.SCHOOLINFO) self.classes_pickle_obj = my_pickle.MyPickle(config.CLASSES_OBJ) self.course_pickle_obj = my_pickle.MyPickle(config.COURSE_OBJ) def exit(self): exit() #往文件里面添加内容的时候写成统一的方法 #因为它既没有引用类的属性,也没有引用对象的属性,所以把它做成非绑定方法 @staticmethod def userinfo_handler(content): with open(config.USERINFO,\'a\') as f: f.write(\'\\n%s\' % content) def show(self,pickle_obj): #反射 pick_obj = getattr(self,pickle_obj) #执行一个生成器函数就拿到一个生成器对象,这里拿到的每一个值,都是生成器返回的对象 load_g = pick_obj.loaditer() for course_obj in load_g: for i in course_obj.__dict__:#### print(\'%s: %s\'%(i,course_obj.__dict__[i])) print(\'*\' * 20) def show_school(self): print(\'校区信息如下:\') for i,v in enumerate(config.school_class,1): print(\'%s: %s\'% (i,v)) def show_teachers(self): self.show(\'teacher_pickle_obj\') def show_courses(self): print(\'课程信息如下:\') for i,v in enumerate(config.school_class): print(\'学校:%s-->课程:%s\' % (v,config.school_class[v])) def show_classes(self): self.show(\'classes_pickle_obj\') def create_teacher(self): l = [] with open(config.USERINFO,\'r\') as f: for line in f: username,v,b = line.strip().split(\'|\') l.append(username) teacher_name = input(\'请输入老师的姓名:\') if teacher_name in l: print(\'\\033[1;31m该讲师已经存在!\\033[0m\') return teacher_pass = input(\'请输入老师的密码:\') self.show_school() teacher_school = input(\'请输入所属的学校:(Beijing|Shanghai)\') #存入文件 content = \'%s|%s|Teacher\' % (teacher_name,teacher_pass) Manager.userinfo_handler(content) #根据输入的姓名与学校值实例化一个老师对象 teacher1 = teacher.Teacher(teacher_name,teacher_school)###实例化 self.teacher_pickle_obj.dump(teacher1) print(\'\\033[0;32m讲师创建成功!\\033[0m\') write_log(\'创建了讲师:%s\' % teacher_name) def create_classes(self): #注意,新建的班级名字不能是已经存在的 classes_names = file_name(config.STUDENTINFO) print(\'\\033[0;32m已经存在的班级如下:\\033[0m\') for i,v in enumerate(classes_names,1): print(\'%s: %s\' % (i,v)) class_name = input(\'请输入您要新建的班级名称:\') if class_name in classes_names: print(\'\\033[1;31m该班级已经存在!\\033[0m\') return school_name = input(\'请输入所属的学校:(Beijing|Shanghai)\') if school_name not in \'Beijing|Shanghai\'.split(\'|\'): print(\'\\033[1;31m请输入正确的学校!\\033[0m\') return course_name = input(\'请输入课程名称:(python|linux|go)\') if course_name not in \'python|linux|go\'.split(\'|\'): print(\'\\033[1;31m请输入正确的课程!\\033[0m\') return #判断 Beijing只能有python与linux,Shanghai只能有go: if (school_name == \'Beijing\' and (course_name ==\'python\' or course_name == \'linux\')) or (school_name == \'Shanghai\' and course_name == \'go\'): #如果符合条件的话新建一个路径 student_path = os.path.join(config.STUDENTINFO,class_name) #利用上面的路径创建一个空文件 open(student_path,\'w\').close() class_obj = school.Classes(school_name,class_name,course_name) #利用pickle dump实例化的对象,这一点json做不到! self.classes_pickle_obj.dump(class_obj)####### print(\'课程 %s 创建成功!\' % course_name) write_log(\'创建了课程:%s\' % course_name) else: print(\'\\033[1;31m您填写的学校与课程的关系不存在!\\033[0m\') return def create_student(self): student_name = input(\'请输入学生姓名:\') student_pass = input(\'请输入学生密码:\') #列举出所有存在的班级 classes_names = file_name(config.STUDENTINFO) print(\'\\033[0;32m已经存在的班级如下:\\033[0m\') for i, v in enumerate(classes_names, 1): print(\'%s: %s\' % (i, v)) student_class = input(\'请输入学生所在的班级:\') class_g = self.classes_pickle_obj.loaditer() for clas in class_g: #这里有既有班级名卡控,不用做判断了 if clas.name == student_class: #先把用户名、密码、角色写入userinfo文件中 content = \'%s|%s|Student\' % (student_name,student_pass) Manager.userinfo_handler(content) #实例化 stu_obj = student.Student(student_name,clas) student_path = os.path.join(config.STUDENTINFO,student_class) my_pickle.MyPickle(student_path).dump(stu_obj) print(\'学生 %s 创建成功!\' % student_name) write_log(\'学生 %s 创建成功!\' % student_name) return else: print(如何使用 xcode 将快照划分为多个片段,以便让用户与每个片段进行交互?简单输入输出交互。 用户输入两个数字,计算并输出两个数字之和:(尝试只用一行代码实现这个功能) 输入半径,计算圆的面积。简单输入输出交互。 用户输入两个数字,计算并输出两个数字之和:(尝试只用一行代码