摘要:对不同的类型进行对应的操作提供帮助主函数,提供用户输入界面。对用户输入的语法正确性镜像解析,并最终解析成字典格式表执行程序链接程序运行命令程序正文执行脚本主入口程序主函数获取用户输入,并对用户进行解析。
程序要求
文件存储时可以这样表示
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种查询语法:
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需自增语法:
add to staff_table values Alex Li,25,134435344,IT,2015-10-29
可删除指定员工信息纪录,输入员工id,即可删除语法:
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
以上每条语名执行完毕后,要显示这条语句影响了多少条纪录。比如查询语句就显示查询出了多少条、修改语句就显示修改了多少条等。
注意:以上需求,要充分使用函数,请尽你的最大限度来减少重复代码!
编写思路 程序目录结构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链接
程序运行命令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"selects(.*?)sfroms(.*?)swheres(.*)", 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"addstos(.*?)svaluess(.*)", 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"delsfroms(.*?)swheres(.*)", 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"updates(.*?)ssets(.*?)=(.*?)swheres(.*)", 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(" ").split(",") == title: continue else: for values in line.strip(" ").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()) + " " for values in data: temp_list = [] for value in values.values(): temp_list.append(str(value)) value2 += ",".join(temp_list) + " " 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_dictREADME
README.md
学习笔记文件处理笔记
函数基础笔记
函数高阶笔记
模块笔记(待修改)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/44562.html
摘要:如果初学者接触的第一门语言是,学习曲线则会平滑得多,掌握一些基本语法和内置的数据结构,已经可以上手写一些小工具或者小型应用。如果你的学习时间充足,我的建议是一定要学数据结构和算法。 前言 Python是最容易入门的编程语言,没有之一。如果初学者接触的第一门语言是C或者C++,对他们来说最难的不是语法,而是容易出现内存泄漏、指针等问题。有时候排查这些问题对初学者的打击很大,尤其是没掌握排...
摘要:所以就找外包公司,找到一个有经验的程序员来做,这样做既可以保证质量,有可以跟上进度。为什么不建议去外包为什么不要去外包公司总体原因如下没有归属感想想工作周围大部分不是自己的同事,想找人说个话都难。 前言 最近有好多人讨论外包,前几天看到一个帖子说就是有一个外包吃了公司的的零食,遭到HR当场批评, 搞的整个IT界备受关注,那么外包公司和非外包公司有什么样的不一样呢?我今天也说说我的看法! ...
摘要:表示需要拦截的请求类型。表示数据模板,可以是对象或字符串。表示用于生成响应数据的函数。指向本次请求的选项集。生成规则是可选的。返回成功的数据,就是登录成功了,否则相反。模拟登录接下来介绍模拟表格增删改查。 前言 关于mockjs,官网描述的是 1.前后端分离 2.不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据。 3.数据类型丰富 4.通过随机数据,模拟各种场景。 5...
?程序员小王的博客:程序员小王的博客 ? 欢迎点赞 ? 收藏 ⭐留言 ? ? 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 ?java自学的学习路线:java自学的学习路线 一、员工管理系统项目说明: 该项目主要是完成Spring+SpringMVC+mybatis的完整整合,功能实现比较单一,就是一个完成增删改查的小项目! 源代码在githee仓库:SSM实战项目...
阅读 916·2021-11-08 13:22
阅读 2840·2021-09-29 09:45
阅读 2823·2021-09-09 11:52
阅读 2257·2019-08-30 13:20
阅读 3738·2019-08-29 13:28
阅读 1354·2019-08-29 12:32
阅读 2719·2019-08-29 11:10
阅读 1642·2019-08-26 13:34