[Python学习日记-58] 开发基础练习1——员工信息查询
简介
该练习结合了函数和一些常用的模块开发了一个使用命令行交互的员工信息查询程序,可以巩固实践之前学习的内容。
题目
一、程序需求
现要求你写⼀个简单的员⼯信息增删改查程序,需求如下:
staff_id | name | age | phone | dept | enroll_date |
---|---|---|---|---|---|
1 | Jove Zou | 22 | 15864987526 | IT | 2020-08-01 |
2 | Lucy Wang | 30 | 13058496789 | HR | 2016-05-25 |
3 | Mary Li | 25 | 17591992555 | Sales | 2019-12-19 |
4 | Jack Chen | 60 | 13532334478 | HR | 2021-03-11 |
该表在文件中的存储方式:
文件名:staff_table(文件内容如下)
# 序号(1),姓名(2),年龄(3),手机号(4),部分(5),入职时间(6)
id,name,age,phone,dept,enroll_data
1,Jove Zou,22,15864987526,IT,2020-08-01
2,Lucy Wang,30,13058496789,HR,2016-05-25
3,Mary Li,25,17591992555,Sales,2019-12-19
4,Jack Chen,60,13532334478,HR,2021-03-11
5,Rachel Chen,23,13351024606,IT,2013-03-16
6,Eric Liu,19,18531054602,Marketing,2012-12-01
7,Cao Zang,21,13235324334,Administration,2011-08-08
8,Kevin Chen,22,13151054603,Sales,2013-04-01
9,Shit Wen,20,13351024602,IT,2017-07-03
10,Mosson1,18,13678789527,IT,2018-12-11
文件(staff_table)行数据的说明:
(1)表示文件中的条目数
(2)表示员工姓名
(3)表示员工的年龄
(4)员工的手机号
(5)表示该员工的部门
(6)员工入职时间
提示:每一行的字符串信息通过逗号分隔成为一个列表 [id,name,age,phone,dept,date]
二、程序功能
对用户输入的字符串进行解析,从文件中筛选出相应符合条件的结果集。
1、查文件(find)
功能演示1:
>>>:find name,age from staff_table where age > 22
>>>:find name from staff_table where age > 22
>>>:find name,age,phone,dept from staff_table where age > 22
提示:name和age之间 只有⼀个逗号没有空格
从 staff_table 文件中,找出员工年龄在22岁以上的员工,将这些员工的姓名,员工的年龄打印出来,对用户输入字符串的解析流程如下:
- 读文件
- 将每⼀个员工的年龄与22进行比较
- 获取到员工年龄大于22的员工信息
- 从符合条件的员工信息中筛选出员工的姓名、年龄
效果如下:
提示:find 与 from 之间可以是 *(* 表示员工的所有信息)也可以是员工信息的任意字段(多个字段可以用英文逗号隔开)
功能演示2:
>>>:find * from staff_table where dept = "IT"
从 staff_table 文件中找到 IT 部门的员工,并打印员工的所有信息。
效果如下:
功能演示3:
>>>:find * from staff_table where enroll_data like "2013"
要求为,从 staff_table 文件中找到员工的入职时间是2013年的员工,并打印员工所有的信息。
效果如下:
2、添加员工信息(用户的手机号不允许重复)
>>>:add staff_table Mosson,18,13678789527,IT,2018-12-11
添加员工信息时,必须有员工名称(Mosson)、员工年龄(18)、员工手机号(13678789527)、员工部门(IT)、员工入职时间(2018-12-11);将这些信息追加到 staff_table 文件新的一行中,并插入这一行的 id
注意:添加员工的时候不考虑异常情况,在添加的时候按照姓名,年龄,手机号, 部门,入职时间 且每一条数据都包含员工的完整数据(姓名、年龄、手机号、部门、入职时间)
效果如下:
3、删除员工信息(根据序号删除相应员工的信息)
>>>:del from staff_table where id = 10
从 staff_table 中删除序号 id 为10的这⼀条员工的信息。
效果如下:
4、修改员工信息(可以根据特殊条件修改员工的信息)
功能演示1:
>>>:update staff_table set dept="Market" where dept = "IT"
将 staff_table 中 dept 为 IT 的修改成 dept 为 Market。
效果如下:
功能演示2:
>>>:update staff_table set age=25 where name = "Jove Zou"
将 staff_table 中用户名为 Jove Zou 的用户的年龄改成25。
效果如下:
答案
程序运行流程图:
在开发程序前最好还是先画一个程序的运行流程图,这样程序的开发逻辑会非常清晰,我们画这个图的时候可以上网注册一个 processon(https://www.processon.com/)或者下载一个 Visio 来画流程图。
目录结构:
Employer_info/
| -- __init__.py # 代表 Employer_info 是一个包,无代码
| -- employer_info.py
| -- README.md
| -- staff_table # 该数据与题目中的一致
employer_info.py:
# -*- coding:utf-8 -*-
def read_file(f_n):
try:
f = open(f_n, 'r', encoding='utf-8')
info_d = {}
f.seek(0)
for line in f: # 读取文件中的内容并转换为dict
info_d[line.split(',')[0]] = line.strip().split(',')
f.close()
return info_d
except:
print("The file is not available...")
def analysis(cmd):
def char_optimization(in_c_l): # 字符串优化函数,优化名字当中有空格的情况
if '<' in cmd[cmd.index('where ') + 6:]: # 如果是del的话符号的序号为5 in_c_l[5 if in_c_l[0] == 'del' else 6]
if in_c_l[0] == 'update': # 对update当中的set name的时候作出处理
before_str = cmd[:cmd.index(' set') + 4]
middle1_str = cmd[cmd.index('set ') + 4:cmd.index(' where')]
middle2_str = cmd[cmd.index('where '):cmd.index(' <') + 2]
after_str = cmd[cmd.index('< ') + 2:]
in_c_l_result = before_str.strip().split() # 合拼为list
in_c_l_result.append(middle1_str)
in_c_l_result.extend(middle2_str.strip().split())
in_c_l_result.append(after_str)
else: # 其他语句的处理方式
before_str = cmd[:cmd.index(' <') + 2]
after_str = cmd[cmd.index('< ') + 2:]
in_c_l_result = before_str.strip().split()
in_c_l_result.append(after_str)
elif '>' in cmd[cmd.index('where ') + 6:]:
if in_c_l[0] == 'update':
before_str = cmd[:cmd.index(' set') + 4]
middle1_str = cmd[cmd.index('set ') + 4:cmd.index(' where')]
middle2_str = cmd[cmd.index('where '):cmd.index(' >') + 2]
after_str = cmd[cmd.index('> ') + 2:]
in_c_l_result = before_str.strip().split()
in_c_l_result.append(middle1_str)
in_c_l_result.extend(middle2_str.strip().split())
in_c_l_result.append(after_str)
else:
before_str = cmd[:cmd.index(' >') + 2]
after_str = cmd[cmd.index('> ') + 2:]
in_c_l_result = before_str.strip().split()
in_c_l_result.append(after_str)
elif '=' in cmd[cmd.index('where ') + 6:]:
if in_c_l[0] == 'update':
before_str = cmd[:cmd.index(' set') + 4]
middle1_str = cmd[cmd.index('set ') + 4:cmd.index(' where')]
middle2_str = cmd[cmd.index('where '):cmd.index(' =') + 2]
after_str = cmd[cmd.index('= ') + 2:]
in_c_l_result = before_str.strip().split()
in_c_l_result.append(middle1_str)
in_c_l_result.extend(middle2_str.strip().split())
in_c_l_result.append(after_str)
else:
after_str = cmd[cmd.index('= ') + 2:]
before_str = cmd[:cmd.index(' =') + 2]
in_c_l_result = before_str.strip().split()
in_c_l_result.append(after_str)
elif 'like' in cmd[cmd.index('where ') + 6:]:
if in_c_l[0] == 'update':
before_str = cmd[:cmd.index(' set') + 4]
middle1_str = cmd[cmd.index('set ') + 4:cmd.index(' where')]
middle2_str = cmd[cmd.index('where '):cmd.index(' =') + 2]
after_str = cmd[cmd.index('= ') + 2:]
in_c_l_result = before_str.strip().split()
in_c_l_result.append(middle1_str)
in_c_l_result.extend(middle2_str.strip().split())
in_c_l_result.append(after_str)
else:
after_str = cmd[cmd.index('like ') + 5:]
before_str = cmd[:cmd.index(' like') + 5]
in_c_l_result = before_str.strip().split()
in_c_l_result.append(after_str)
else:
in_c_l_result = []
return in_c_l_result
c_l = cmd.split()
c_l_result = []
# 赋值需要返回的变量
if c_l[0] == 'find' and len(c_l) >= 8:
c_l_result = char_optimization(c_l)
f_n = c_l[3]
elif c_l[0] == 'update' and len(c_l) >= 8:
c_l_result = char_optimization(c_l)
f_n = c_l[1]
elif c_l[0] == 'del' and len(c_l) >= 7:
c_l_result = char_optimization(c_l)
f_n = c_l[2]
elif c_l[0] == 'add' and len(c_l) >= 3:
c_l_result = c_l
f_n = c_l[1]
else:
f_n = None
return c_l_result, f_n
def header_analysis(k, sec_l, d):
search_list = sec_l[1].split(',') # 记录查询项列表
yc_position = [] # 记录显示项的序号
s_position = d[k].index(sec_l[5]) # 记录需要比较的值在list当中的序号
if sec_l[1] == '*': # 如果是'*'直接赋值所有项
search_list = d[k]
for i in search_list:
yc_position.append(d[k].index(i)) # 记录需要显示的值在list当中的序号
return search_list, yc_position, s_position
def display(y_code, yc_position, d_r): # 打印出符合的值
p_list = [] # 返回匹配到的信息
for k in d_r:
p_str = '' # 输出的str
for i in range(0, len(yc_position)): # 合拼需要打印的值
p_str += y_code[i] + ' ' + d_r[k][yc_position[i]] + ' '
p_list.append(p_str)
return p_list
def search(sec_l, d):
search_list = [] # 记录查询项列表
yc_position = [] # 记录显示项的序号
s_position = None # 记录比较项的序号
first_key = True # 判断是否为表头
d_result = {} # 记录比较结果
if len(sec_l) == 8:
for k in d:
if first_key: # 表头信息获取
if sec_l[5] in d[k]:
search_list, yc_position, s_position = header_analysis(k, sec_l, d)
first_key = False
else:
print("Parameter is not in the table...")
break
else:
if sec_l[6] == '>' and sec_l[7].isdigit():
if d[k][s_position] > sec_l[7]:
d_result[k] = d[k]
elif sec_l[6] == '<' and sec_l[7].isdigit():
if d[k][s_position] < sec_l[7]:
d_result[k] = d[k]
elif sec_l[6] == '=':
if d[k][s_position] == sec_l[7].strip('\"'):
d_result[k] = d[k]
elif sec_l[6] == 'like':
if sec_l[7].strip('\"') in d[k][s_position]:
d_result[k] = d[k]
else:
print("Sorry,the comparison type is not supported...")
for line in display(search_list, yc_position, d_result): # 调用函数打印在终端
print(line)
return d_result
else:
print("Sorry,the command is not supported...\nPlease input the comparison value.")
def add(add_l, d):
staff_id = d.keys().__len__() # 记录最新序号
f_n = add_l[1] # 记录需要查询的文件名
f = open(f_n, 'a', encoding='utf-8') # 在文件的末尾添加,所以使用追加模式
if len(add_l) == 3:
f.write(str(staff_id) + ',' + add_l[2] + '\n') # 写入文件
else:
print("Sorry,the command is ERROR")
f.close()
def delete(del_l, d):
f_del = open(del_l[2], 'w', encoding='utf-8')
if len(del_l) == 7:
for k in d:
if del_l[5] == '<' and del_l[6].isdigit():
if k < del_l[6]:
continue
elif del_l[5] == '>' and del_l[6].isdigit():
if k > del_l[6]:
continue
elif del_l[5] == '=':
if k == del_l[6].strip('\"'):
continue
else:
print("Sorry,the comparison type is not supported...")
f_del.write(','.join(d[k]) + '\n')
else:
print("Sorry,the command is ERROR")
f_del.close()
def modify(mod_l, d):
if len(mod_l) == 8:
sec_l = 'find * from %s where %s = %s' % (mod_l[1], mod_l[5], mod_l[7]) # 转换成search的语法,后面调用search()来找出需要修改的信息
mod_c_l, mod_f_n = analysis(sec_l)
print("------- Modify info -------")
mod_d = search(mod_c_l, d) # 需要修改的员工信息
set_yc_position = mod_l[3].split('=')[0] # 需要修改这个参数
set_value = mod_l[3].split('=')[1].strip('\"') # 需要改为这个值
mod_yc_position = d['id'].index(set_yc_position) # 定位修改信息的位置
f_mod = open(mod_f_n, 'w', encoding='utf-8')
for k in mod_d: # 修改符合条件的条目
d[k][mod_yc_position] = set_value
for k in d: # 写入文件
f_mod.write(','.join(d[k]) + '\n')
f_mod.close()
else:
print("Sorry,the command is ERROR")
func_dict = {
'add': add,
'del': delete,
'find': search,
'update': modify
}
while True:
# 准备阶段
"""
0:id
1:name
2:age
3:phone
4:dept
5:enroll_date
"""
command = input(">>>>>:").strip()
if not command: # 不能输入空命令
print("Please input command...")
else:
cmd_list, file_name = analysis(command)
if file_name is not None and cmd_list != []: # 命令经过处理后返回的值不能为空,为空就是命令有错
info_dict = read_file(file_name)
if info_dict != {}: # 读取到文件后字典一定不能为空
if cmd_list[0] in func_dict: # 判断find add del update
func = func_dict.get(cmd_list[0])
func(cmd_list, info_dict)
else:
print("Not this functions,available functions:add del find update...")
else:
print("Sure your file name...")
else:
print("CMD is bad...")
README.md(没开发完成一个程序就应该写一个):
标签:index,58,Python,cmd,员工,result,str,where,日记 From: https://blog.csdn.net/zjw529507929/article/details/143315752开发环境
Python (3.12.4)实现功能
该程序包含了对员工信息的 查询(find) 增加(add) 删除(del) 修改(update)这四个功能,输入的命令需要严格遵守语法规则
示例当中的符号示意:{} 当中的option必填其之一,| 或,* 代表所有,option_* 任意option,[] 必填;当中规定的空格是严格规定的
查询(find)
find {option_1|option_1,...,option_n|*} from [filename] where [option_* {<|>|=} {digit|string}] # < > 必须为digit
增加(add)
add [filename] [info]
删除(del)
del from [filename] where [option_* {<|>|=} {digit|string}] # < > 必须为digit
修改(update)
update [filename] set [option_*[=]{digit|string}] where [option_* {<|>|=} {digit|string}]导入虚拟数据
./staff_table启动项目
进入到程序所在目录
./Employer_info/
python employer_info.py常见问题
问题
终端执行python错误
解决
设置环境变量,Windows在Path当中添加Python安装的所在路径
问题
命令当中涉及到大小判断时输入字符可能会报错,而不是语句提示
解决
目前该bug还未解决