一:需求
homework.txt文件中有如下格式的人员信息:
1,Jack Wang,28,13451024608,HR,2015‐01‐07
2,Rain Wang,21,13451054608,IT112,2017‐04‐01
3,Mack Qiao,44,15653354208,Sales,2016‐02‐01
4,Rachel Chen,23,13351024606,IT112,2013‐03‐16
5,Eric Liu,19,18531054602,Marketing,2012‐12‐01
6,Chao Zhang,21,13235324334,Administration,2011‐08‐08
7,Kevin Chen,22,13151054603,Sales,2013‐04‐01
8,Shit Wen,20,13351024602,IT112,2017‐07‐03
9,Shanshan Du,26,13698424612,Operation,2017‐07‐02
10, whw,25,185310546502,IT,2015‐10‐29
11, wh3w,26,185310544602,IT,2015‐10‐29
对应的Key值为:['id','name','age','phone','dept','enrolled_date']
要求实现基本的增删改查功能,并且数据需要实时更新~
find name,age from homework where age > 22
find * from homework where age > 22
del from homework where id = 2
update homework set dept=IT11 where dept = IT
add homework whw,25,18531054602,IT,2015‐10‐29(如果有相同的Phone值提示重复,不可以增加)
二、这里直接上代码~~需要交流请站内信~
#说明:为了消除add后再find时不会出现新增的条目的问题,将load_db()方法分别写入了各函数中,为的就是要实现数据的实时更新
import os
DB_FILE ='homework.txt'
colums = ['id','name','age','phone','dept','enrolled_date']#字典data的键
#提示加粗
def print_log(msg,log_type = 'info'):
if log_type == 'info':
print(msg)
elif log_type == 'error':
print('\033[31;1m %s\033[0m'% msg)
def load_db(db_file):
'''
加载员工信息并转成指定的格式
:return:
'''
data = {}#先定义一个空字典
for i in colums:
data[i] = []#空字典每个键对应一个空列表,放具体值
f = open(db_file,'r',encoding='gb18030',errors='ignore') #gb18030比gbk多 (日期的 - 字符需要改正)
for line in f:
staff_id,name,age,phone,dept,enrolled_date = line.split(',')#利用split()方法 每隔一个逗号分隔文件内容,并将值赋给临时变量
data['id'].append(staff_id)
data['name'].append(name)
data['age'].append(age)
data['phone'].append(phone)
data['dept'].append(dept)
data['enrolled_date'].append(enrolled_date) #临时变量的值追加到colums中
f.close()
return data
#自定义分隔出的右半部分的取值操作方式:
#大于
def op_gt(column,condition_val):
'''
:param column: eg.age
:param condition_val:eg.22
:return:[[id,name,age,...]] 返回一个输入的键组成的列表
'''
staff_data = load_db('homework.txt')
matched_records = []#符合条件的人员信息的拼起来的列表,且顺序也不能错
for index,val in enumerate(staff_data[column]):#枚举
if float(val) > float(condition_val):#将字符串转换为数字,匹配上了
#print('match:',val) 打印符合条件的“年龄值”
record = []
for col in colums:
record.append(staff_data[col][index])#按顺序将符合匹配的数据加进去,放到临时的小列表中
matched_records.append(record) #将组合好的小列表加到大列表中去,得到的是符合条件的每个人的信息
#print('matched records:',matched_records) #打印符合条件的人员信息,大列表嵌套小列表的形式
return matched_records
#小于
def op_lt(column,condition_val):
'''
:param column: eg.age
:param condition_val:eg.22
:return:[[id,name,age,...]] 返回一个输入的键组成的列表
'''
staff_data = load_db('homework.txt')
matched_records = [] # 符合条件的人员信息的拼起来的列表,且顺序也不能错
for index, val in enumerate(staff_data[column]): # 枚举
if float(val) < float(condition_val): # 将字符串转换为数字,匹配上了
# print('match:',val) 打印符合条件的“年龄值”
record = []
for col in colums:
record.append(staff_data[col][index]) # 按顺序将符合匹配的数据加进去,放到临时的小列表中
matched_records.append(record) # 将组合好的小列表加到大列表中去,得到的是符合条件的每个人的信息
# print('matched records:',matched_records) #打印符合条件的人员信息,大列表嵌套小列表的形式
return matched_records
#等于
def op_eq(column,condition_val):
'''
:param column: eg.age
:param condition_val:eg.22
:return:[[id,name,age,...]] 返回一个输入的键组成的列表
'''
staff_data = load_db('homework.txt')
matched_records = [] # 符合条件的人员信息的拼起来的列表,且顺序也不能错
for index, val in enumerate(staff_data[column]): # 枚举 age
if val == condition_val: # 匹配上了
# print('match:',val) 打印符合条件的“年龄值”
record = []
for col in colums:
record.append(staff_data[col][index]) # 按顺序将符合匹配的数据加进去,放到临时的小列表中
matched_records.append(record) # 将组合好的小列表加到大列表中去,得到的是符合条件的每个人的信息
# print('matched records:',matched_records) #打印符合条件的人员信息,大列表嵌套小列表的形式
return matched_records
#like
def op_like(column,condition_val):
'''
:param column: eg.age
:param condition_val:eg.22
:return:[[id,name,age,...]] 返回一个输入的键组成的列表
'''
staff_data = load_db('homework.txt')
matched_records = [] # 符合条件的人员信息的拼起来的列表,且顺序也不能错
for index, val in enumerate(staff_data[column]): # 枚举
if condition_val in val: # 匹配上了
# print('match:',val) 打印符合条件的“年龄值”
record = []
for col in colums:
record.append(staff_data[col][index]) # 按顺序将符合匹配的数据加进去,放到临时的小列表中
matched_records.append(record) # 将组合好的小列表加到大列表中去,得到的是符合条件的每个人的信息
# print('matched records:',matched_records) #打印符合条件的人员信息,大列表嵌套小列表的形式
return matched_records
def syntax_where(clause): #clause是where右边的部分
'''
解析where条件,并过滤数据
:param clause: 比如:age>22
:return:matched_data
'''
#也可以为每种情况定义一种方式:
#column,operator,condition = clause.split('>')或者column,operator,condition = clause.split('<')......
operators = {
'>':op_gt,
'<':op_lt,
'=':op_eq,
'like':op_like,
}
for op_key,op_func in operators.items():#op_key为符号< > 等,op_func为函数的内存地址
if op_key in clause:
column,val = clause.split(op_key) #按照符号分割:age 22
matched_data = op_func(column.strip(),val.strip())#真正去查询数据
return matched_data
else:#在for执行完成且没有中间被break的情况下 才执行,也就是说没有匹配上任何的条件公式
print_log('语法错误:where条件只能支持[>,<,=,like]','error')
#find方法 只是查找
def syntax_find(data_set,left):#data_set里就是matched_data中的内容
'''
解析查询语句,并从deta_set中打印指定的列
:param data_set: eg.['1', 'Alex Li', '22', '13651054608', 'IT', '2013-04-01\n'], ['3', 'Rain Wang', '21', '13451054608', 'IT', '2017-04-01\n']]
:param left: find name,age from homework #find分一次 from分一次
:return:
'''
filter_cols_tmp = left.split('from')[0][4:].split(',')#先按照from分,然后按照find分,找到关键字
filter_cols = [i.strip() for i in filter_cols_tmp] #过滤空格 干净的columns 去掉关键字的空格 可以只打印指定关键字的列
if '*' in filter_cols[0]:
for i in data_set:
print(i)
print('成功查询到%s条数据' % len(data_set))
else:
reformat_data_set = []
for row in data_set:
filter_vals = []#把要打印的字段放在列表中
for col in filter_cols:
col_index = colums.index(col) #通过colums拿到关键字列的索引值,依据次取出每条记录里对应的索引的值
filter_vals.append(row[col_index])
reformat_data_set.append(filter_vals)
for i in reformat_data_set:
print(i)
print('成功查询到%s条数据' % len(data_set))
#del方法
def syntax_delete(data_set,left):
'''
:param data_set: eg.['1', 'Alex Li', '22', '13651054608', 'IT', '2013-04-01\n']
:param left: del from homework where id =1
:return:
'''
for matched_row in data_set:
staff_id = matched_row[0].strip()#找到id值
f = open('homework.txt','r',encoding='gb18030',errors='ignore')
f1 = open('homework_new.txt','w',encoding='gb18030',errors='ignore')
for line in f:
in_list = line.split(',')
if in_list[0] < staff_id:
f1.write(line)
elif in_list[0] > staff_id:
in_list[0] = str(int(in_list[0])-1)
f1.write(','.join(in_list))
else:continue
f.close()
f1.close()
os.replace('homework_new.txt','homework.txt')
print('删除%s条记录!' % len(data_set))
#update方法
def syntax_update(data_set,left):
'''
:param data_set: 与find一样 eg.['1', 'Alex Li', '22', '13651054608', 'IT', '2013-04-01\n']
:param left: update homework set dept=IT11 where dept = IT
:return:
'''
staff_data = load_db('homework.txt')
formula_raw = left.split('set')
if len(formula_raw) > 1: # 有set关键字
col_name, new_val = formula_raw[1].strip().split('=') # age = 25 col_name里是age,new_val 里是25
col_index = colums.index(col_name) # 在coluns中找到对应关键字的索引
# 循环data_set,取到每条记录的ID,拿着这个ID到STAFF_DATA['id']里找对应的id的索引,拿到索引去STAFF_DATA['age']列表里,改对应索引的值
for matched_row in data_set:
staff_id = matched_row[0]
staff_id_index = staff_data['id'].index(staff_id)
staff_data[col_name][staff_id_index] = new_val
# !!把修改后的数据存到硬盘上
f1 = open('%s.new' % DB_FILE, 'w', encoding='gb18030', errors='ignore')
for i,v in enumerate(staff_data['id']):
row = []
for col in colums:
row.append(staff_data[col][i])
f1.write(','.join(row))
f1.close()
os.replace('homework.txt.new','homework.txt')
#save_db()
print('成功修改了%s条数据' % len(data_set))
else:
print_log('语法错误:未检测到set关键字', 'error')
#add 方法
def syntax_add(data_set,left):
'''
总体思路是先将left字符串按照homework split 切割成两部分,第一部分改成id 后一部分不变,这样就变成了想要的格式,在join 最后写进去新文件就行!
:param data_set: 整个表
:param left: 装的是完整的 add homework whw,25,18531054602,IT,2015‐10‐29
:return:
'''
while 1:
#add方法中,为了获得最新的行数的信息,必须每增加一次前打开最新的txt文件以获取最新的行数:
staff_data = load_db('homework.txt')
cmd_add_list = left.strip().split('homework') #['8', ' whw,25,134435344,IT,2015‐10‐29']
cmd_add_list[0] = str(len(staff_data['phone'])+1)
#print(cmd_add_list)
add = ','.join(cmd_add_list) #add 里 就是我们想要的最后添加进去的字符串
s = cmd_add_list[1].split(',') #s 里是:[' whw', '25', '134435344', 'IT', '2015‐10‐29']
if s[2].strip() in staff_data['phone']:
print('记录中已经有重复的手机号,请重新输入')
break
else:
f = open('homework.txt', 'a', encoding='gb18030', errors='ignore')#a模式
f.write('\n')
f.write(add)
f.close()
print('增加了1条记录!')
break
def syntax_parser(cmd):
'''
解析语句并执行,是否合法
:param cmd:
:return:
'''
syntax_list = {
'find': syntax_find,
'del': syntax_delete,
'update': syntax_update,
'add': syntax_add
}
staff_data = load_db('homework.txt')
if cmd.split()[0] in ('find','add','del','update'):
if 'where' in cmd:#含where语句的
left,right = cmd.split('where') #用split方法将语句按照where切割成左右两个部分!
#print(left,right) #中途打印 查看where前后部分用split断开了
matched_record = syntax_where(right)#找到右边的
else:#不包含where语句的
matched_record = []
for index,staff_id in enumerate(staff_data['id']):
record = []
for col in colums:
record.append(staff_data[col][index])
matched_record.append(record)
left = cmd
cmd_action = cmd.split()[0]#注意去掉空格
if cmd_action in syntax_list:
syntax_list[cmd_action](matched_record,left)#匹配上了
else:
print_log('语法错误:\n[find\\add\del\\update] from [colum...] from [homework] [where] [name...] [colum] [>/</=/like] [...] ','error')
def main():
'''
让用户输入语句,并执行
:return:
'''
while 1:
cmd = input('staff_db:').strip()
if not cmd:continue#如果为空 继续
syntax_parser(cmd.strip())#传入值得时候讲空格去掉
#开始执行程序
if __name__ =="__main__":#仅在本模块运行main(),其他模块调用的时候不用启动
main()