文件存储时能够这样表示python
id,name,age,phone,dept,enroll_date 1,Alex Li,22,13651054608,IT,2013-04-01 2,Jack Wang,28,13451024608,HR,2015-01-07 3,Rain Wang,21,13451054608,IT,2017-04-01 4,Mack Qiao,44,15653354208,Sales,2016-02-01 5,Rachel Chen,23,13351024606,IT,2013-03-16 6,Eric Liu,19,18531054602,Marketing,2012-12-01 7,Chao Zhang,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,Shanshan Du,26,13698424612,Operation,2017-07-02
可进行模糊查询,语法至少支持下面3种查询语法:mysql
select name,age from staff_table where age > 22 select * from staff_table where dept = "IT" select * from staff_table where enroll_date like "2013"
可建立新员工纪录,以phone作惟一键(即不容许表里有手机号重复的状况),staff_id需自增语法:git
add to staff_table values Alex Li,25,134435344,IT,2015-10-29
可删除指定员工信息纪录,输入员工id,便可删除语法:github
del from staff_table where id = 3
可修改员工信息,语法以下:正则表达式
update staff_table set dept = Market where dept = IT #把全部dept=IT的纪录的dept改为Market update staff_table set age = 25 where name = Alex Li #把name=Alex Li的纪录的年龄改为25
注意:以上需求,要充分使用函数,请尽你的最大限度来减小重复代码!sql
homework_project
├── action
│ ├── database.py # 对数据库中的表文件进行操做
│ ├── __init__.py
├── config
│ ├── __init__.py
│ └── syntax.py # 配置文件。
├── core
│ ├── actions.py # 对不一样的sql类型进行对应的操做
│ ├── help.py # 提供帮助
│ ├── __init__.py
│ ├── main.py # 主函数,提供用户输入界面。并执行语法解析与sql操做
│ ├── parsers.py # 语法解析函数。对用户输入的语法正确性镜像解析,并最终解析成字典格式
├── database
│ └── staff_table # 表
├── __init__.py
__init__.py
mysql_run.py # 执行程序数据库
github连接app
python mysql_run.py
mysql_run.py:执行脚本函数
from homework_project.core.main import main if __name__ == '__main__': main()
main.py:主入口程序学习
# -*- coding: utf-8 -*- from . import parsers as p from .actions import actions import os def main(): """ 主函数 获取用户输入,并对用户进行解析。若是获取解析值,并执行相应的sql操做。 """ database_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/database/' # 获取数据库文件的路径 while True: sql_str = input('请输入sql语句>').strip() if sql_str: sql_type = sql_str.split()[0].lower() # 获取输入的sql语句的类型。 if p.parses(sql_type): # 检查sql的类型是否符合规则 dict_sql = p.parses(sql_type)(sql_str, sql_type, database_dir) # 调用parsers模块的parses函数进行语法解析 if dict_sql: # 若是字典格式的sql语句返回 actions(sql_type)(dict_sql) # 则执行后面的sql操做 else: print('sql语法错误,程序支持select,del,add,update语句。') else: continue
parsers.py:sql语法解析模块
# -*- coding: utf-8 -*- import re from .help import help def parses(sql_type): """ 语法解析函数 :param sql_type: 从main()函数导入的sql语句类型。 :return: parsers_dict[sql_type] 相应的语法解析函数 """ parsers_dict = {'select': select_parser, 'add': add_parser, 'del': del_parser, 'update': update_parser} if sql_type in parsers_dict: return parsers_dict[sql_type] else: return False def select_parser(sql_str, sql_type, base_dir): """ 搜索语句解析函数 :param sql_str: 用户输入的sql语句 :param sql_type: 用户输入的sql语句类型 :param base_dir: 主函数导入的数据库所在路径 :return: """ dict_sql = {} # 建立空字典 command_parse = re.search(r'select\s(.*?)\sfrom\s(.*?)\swhere\s(.*)', sql_str, re.I) # 使用正则表达式解析add语法,而且re.I忽略大小写 if command_parse: dict_sql['select'] = command_parse.group(1) dict_sql['from'] = base_dir + command_parse.group(2) # sql字典'from’键添加数据库表文件路径的值 dict_sql['where'] = command_parse.group(3).split(',') # sql字典‘where’键添加插入的值 if logic_cal(dict_sql['where']): # 使用logic_cal函数将where语句语法再次进行解析 dict_sql['where'] = logic_cal(dict_sql['where']) # 如解析有返回值,将返回值从新做为dict_sql['where']的值 return dict_sql else: print(help(sql_type)) # 当语法解析不正常答应帮助 else: print(help(sql_type)) # 当语法解析不正常答应帮助 def add_parser(sql_str, sql_type, base_dir): """ 添加语句解析函数 :param sql_str: 用户输入的sql语句 :param sql_type: 用户输入的sql语句类型 :param base_dir: 主函数导入的数据库所在路径 :return: dict_sql 解析后的字典格式sql语句 """ dict_sql = {} command_parse = re.search(r'add\sto\s(.*?)\svalues\s(.*)', sql_str, re.I) # 使用正则表达式解析add语法,而且re.I忽略大小写 if command_parse: dict_sql['to'] = base_dir + command_parse.group(1) # sql字典'to’键添加数据库表文件路径的值 dict_sql['values'] = command_parse.group(2).split(',') # sql字典‘values’键添加插入的值 return dict_sql else: print(help(sql_type)) # 当语法解析不正常答应帮助 def del_parser(sql_str, sql_type, base_dir): """ 删除语句解析函数 :param sql_str: 用户输入的sql语句 :param sql_type: 用户输入的sql语句类型 :param base_dir: 主函数导入的数据库所在路径 :return: dict_sql 解析后的字典格式sql语句 """ dict_sql = {} command_parse = re.search(r'del\sfrom\s(.*?)\swhere\s(.*)', sql_str, re.I) if command_parse: dict_sql['from'] = base_dir + command_parse.group(1) # sql字典'to’键添加数据库表文件路径的值 dict_sql['where'] = command_parse.group(2).split(',') # sql字典‘where’键添加插入的值 if logic_cal(dict_sql['where']): # 使用logic_cal函数将where语句语法再次进行解析 dict_sql['where'] = logic_cal(dict_sql['where']) # 如解析有返回值,将返回值从新做为dict_sql['where']的值 return dict_sql else: print(help(sql_type)) # 当语法解析不正常答应帮助 else: print(help(sql_type)) # 当语法解析不正常答应帮助 def update_parser(sql_str, sql_type, base_dir): """ 更新语句解析函数 :param sql_str: 用户输入的sql语句 :param sql_type: 用户输入的sql语句类型 :param base_dir: 主函数导入的数据库所在路径 :return: dict_sql 解析后的字典格式sql语句 """ dict_sql = {} command_parse = re.search(r'update\s(.*?)\sset\s(.*?)=(.*?)\swhere\s(.*)', sql_str, re.I) if command_parse: dict_sql['update'] = base_dir + command_parse.group(1) # sql字典'to’键添加数据库表文件路径的值 dict_sql['set'] = [command_parse.group(2), '=', command_parse.group(3)] # sql字典‘where’键添加插入的值 dict_sql['where'] = command_parse.group(4).split(',') if logic_cal(dict_sql['where']) and logic_cal(dict_sql['set']): # 若是where语句、set语句都符合logic_cal中定义的规范 dict_sql['where'] = logic_cal(dict_sql['where']) # 如解析有返回值,将返回值从新做为dict_sql['where']的值 dict_sql['set'] = logic_cal(dict_sql['set']) # 如解析有返回值,将返回值从新做为dict_sql['set']的值 return dict_sql else: print(help(sql_type)) # 当语法解析不正常答应帮助 else: print(help(sql_type)) # 当语法解析不正常答应帮助 def logic_cal(logic_exp): """ 逻辑函数 :param logic_exp: sql语句中和逻辑判断相关的语句,列表格式。如[‘age','>=',20] 或 [‘dept','like','HR'] :return: logic_exp 通过语法解析后的逻辑判断语句。列表格式。如[‘age','==',20] 或 [‘dept','like','HR'] """ # 表达式列表优化成三个元素,形如[‘age','>=',20] 或 [‘dept','like','HR'] logic_exp = re.search('(.+?)\s([=<>]{1,2}|like)\s(.+)', ''.join(logic_exp)) if logic_exp: logic_exp = list(logic_exp. group(1, 2, 3)) # 取得re匹配的全部值,并做为一个列表 if logic_exp[1] == '=': logic_exp[1] = '==' # 判断逻辑运算的比较符号后的值是否字母,而且用户是否输入了双引号。如没有输入手工添加上双引号。 if not logic_exp[2].isdigit() and not re.search('"(.*?)"', logic_exp[2]): logic_exp[2] = '"' + logic_exp[2] + '"' return logic_exp else: return False
actions.py:sql操做模块
# -*- coding: utf-8 -*- from homework_project.action.database import read_db, write_db, print_info from homework_project.config.syntax import get_title import re def actions(sql_type): """ sql操做主函数 :param sql_type: sql语句的类型 :return: actions_dict[sql_type] 相应操做的函数 """ actions_dict = {'select': select_action, 'add': add_action, 'del': del_action, 'update': update_action} if sql_type in actions_dict: # 判断导入的sql类型是否在actions_dict字典中定义。 return actions_dict[sql_type] def select_action(dict_sql): info = dict_sql['select'] data = read_db(dict_sql['from']) # 获取原始数据库文件中的全部数据,data为列表格式 key = dict_sql['where'][0] # 获取sql语句中where语句的key值。如id = 1,获取id count = 0 for values in data: # 读取data列表中的每个元素,values是字典格式 if type(values[key]) is int: value = str(values[key]) else: value = '"' + str(values[key]) + '"' dict_sql['where'][0] = value # 将values[key]的值取出并从新赋值为sql语句的key值。 if where_action(dict_sql['where']): # 将新的where语句,发送给where_action语句进行bool判断。 count += 1 print_info(info, **values) print('已查找%s条记录' % count) def add_action(dict_sql): """ 插入动做 获取用户输入的values,并在表中插入 :param dict_sql: parsers函数处理后的字典格式的sql语句 """ data = read_db(dict_sql['to']) # 获取原始数据库文件中的全部数据 value = dict_sql['values'] # 从dict_sql中获取values的列表 t_id = str(int(data[-1]['id']) + 1) # 获取原始数据库文件中id列最后一行的id数值,并每次自动+1。而后转换为字符串格式 value.insert(0, t_id) # 将添加的id插入到value变量中 if len(value) != len(get_title()): # 判断输入值得长度是否等于数据库文件中定义的列的长度 print('列数不正确') else: data.append(dict(zip(get_title(), value))) # 在获取的原始数据中插入行的数据 print('已添加记录') write_db(dict_sql['to'], data) # 写入文件 def del_action(dict_sql): """ 删除动做函数 :param dict_sql: parsers函数处理后的字典格式的sql语句 """ temp_list = [] data = read_db(dict_sql['from']) # 获取原始数据库文件中的全部数据,data为列表格式 key = dict_sql['where'][0] # 获取sql语句中where语句的key值。如id = 1,获取id for values in data: # 读取data列表中的每个元素,values是字典格式 if type(values[key]) is int: value = str(values[key]) else: value = '"' + str(values[key]) + '"' dict_sql['where'][0] = value # 将values[key]的值取出并从新赋值为sql语句的key值。 if where_action(dict_sql['where']): # 将新的where语句,发送给where_action语句进行bool判断。 temp_list.append(values) # 若是符合条件,就从data中移除对应的values print('已删除%s条记录' % len(temp_list)) for i in temp_list: data.remove(i) write_db(dict_sql['from'], data) # 将新生成的data从新写入文件 def update_action(dict_sql): """ 更新动做函数 :param dict_sql: parsers函数处理后的字典格式的sql语句 """ data = read_db(dict_sql['update']) # 获取原始数据库文件中的全部数据,data为列表格式 key = dict_sql['where'][0] # 获取sql语句中where语句的key值。如id = 1,获取id set_key = dict_sql['set'][0] # 获取set语句中用户输入的key set_value = dict_sql['set'][3].strip("'").strip('"') # 获取set语句中用户输入的value count = 0 for values in data: # 读取data列表中的每个元素,values是字典格式 if type(values[key]) is int: value = str(values[key]) else: value = '"' + str(values[key]) + '"' dict_sql['where'][0] = value # 将values[key]的值取出并从新赋值为sql语句的key值。 if where_action(dict_sql['where']): # 将新的where语句,发送给where_action语句进行bool判断。 count += 1 values[set_key] = set_value # 若是符合条件,使用将set_key的值修改成set_value print('已更新%s条记录' % count) write_db(dict_sql['update'], data) # 将新生成的data从新写入文件 def where_action(condition): """ where语句操做函数 :param condition: 判断语句。就是字典中where的值 :return: """ if 'like' in condition: # 若是like在语句中 # 将where语句中的第二个参数和,第一个参数进行正则比较。若是执行正常就返回True return re.search(condition[2].strip("'").strip('"'), condition[0]) and True else: return eval(' '.join(condition)) # 除此使用eval进行python的逻辑判断
help.py:帮助模块
# -*- coding: utf-8 -*- def help(sql_type): dict = {'select': select_help, 'add': add_help, 'del': del_help, 'update': update_help, } if sql_type in dict: return dict[sql_type]() def select_help(): strings = '''select语法错误。请查看案例: select name,age from staff_table where age > 22 select * from staff_table where dept = "IT" select * from staff_table where enroll_date like "2013" ''' return strings def add_help(): strings = '''add语法错误。请查看案例: add to staff_table values Alex Li,25,134435344,IT,2015-10-29 ''' return strings def del_help(): strings = '''del语法错误。请查看案例: del from staff_table where id = 3 ''' return strings def update_help(): strings = '''update语法错误。请查看案例: UPDATE staff_table SET dept="Market" WHERE dept = "IT" UPDATE staff_table SET age=25 WHERE name = "Alex Li" ''' return strings
database.py:文件读写模块
# -*- coding: utf-8 -*- from homework_project.config.syntax import get_title def read_db(table): """ 读取表文件函数。 :param table: 表文件参数 :return: 返回一个包含表文件内容的字典 """ title = get_title() try: main_list = [] with open(table, 'r', encoding='utf-8') as rf: for line in rf: temp_list = [] if line.rstrip('\n').split(',') == title: continue else: for values in line.strip('\n').split(','): if values.isdigit(): temp_list.append(int(values)) else: temp_list.append(values) main_list.append(dict(zip(title, temp_list))) return main_list except FileNotFoundError as e: print(e) exit(1) def write_db(table, data): """ 写入表文件函数。 :param table: 表文件参数 :param data: 导入的数据。为字典格式 """ value2 = ','.join(get_title()) + '\n' for values in data: temp_list = [] for value in values.values(): temp_list.append(str(value)) value2 += ','.join(temp_list) + '\n' with open(file=table, mode='w', encoding='utf-8') as wf: wf.write(value2) def print_info(info, **kwargs): """ 打印函数。 用于select语句打印显示 :param info: select语句中须要显示的类 :param kwargs: 字典,用于进行操做的原始数据 :return: """ temp_list = [] if info == '*': for key in kwargs: temp_list.append(str(kwargs[key])) print(','.join(temp_list)) else: info_list = info.split(',') for i in info_list: temp_list.append(str(kwargs[i])) print(','.join(temp_list))
sytanx.py:配置文件模块
def get_title(): title_dict = ['id','name','age','phone','dept','enroll_date'] return title_dict