摘要:對(duì)不同的類型進(jìn)行對(duì)應(yīng)的操作提供幫助主函數(shù),提供用戶輸入界面。對(duì)用戶輸入的語(yǔ)法正確性鏡像解析,并最終解析成字典格式表執(zhí)行程序鏈接程序運(yùn)行命令程序正文執(zhí)行腳本主入口程序主函數(shù)獲取用戶輸入,并對(duì)用戶進(jìn)行解析。
程序要求
文件存儲(chǔ)時(shí)可以這樣表示
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
可進(jìn)行模糊查詢,語(yǔ)法至少支持下面3種查詢語(yǔ)法:
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"
可創(chuàng)建新員工紀(jì)錄,以phone做唯一鍵(即不允許表里有手機(jī)號(hào)重復(fù)的情況),staff_id需自增語(yǔ)法:
add to staff_table values Alex Li,25,134435344,IT,2015-10-29
可刪除指定員工信息紀(jì)錄,輸入員工id,即可刪除語(yǔ)法:
del from staff_table where id = 3
可修改員工信息,語(yǔ)法如下:
update staff_table set dept = Market where dept = IT #把所有dept=IT的紀(jì)錄的dept改成Market update staff_table set age = 25 where name = Alex Li #把name=Alex Li的紀(jì)錄的年齡改成25
以上每條語(yǔ)名執(zhí)行完畢后,要顯示這條語(yǔ)句影響了多少條紀(jì)錄。比如查詢語(yǔ)句就顯示查詢出了多少條、修改語(yǔ)句就顯示修改了多少條等。
注意:以上需求,要充分使用函數(shù),請(qǐng)盡你的最大限度來(lái)減少重復(fù)代碼!
編寫思路 程序目錄結(jié)構(gòu)homework_project
├── action
│?? ├── database.py # 對(duì)數(shù)據(jù)庫(kù)中的表文件進(jìn)行操作
│?? ├── __init__.py
├── config
│?? ├── __init__.py
│?? └── syntax.py # 配置文件。
├── core
│?? ├── actions.py # 對(duì)不同的sql類型進(jìn)行對(duì)應(yīng)的操作
│?? ├── help.py # 提供幫助
│?? ├── __init__.py
│?? ├── main.py # 主函數(shù),提供用戶輸入界面。并執(zhí)行語(yǔ)法解析與sql操作
│?? ├── parsers.py # 語(yǔ)法解析函數(shù)。對(duì)用戶輸入的語(yǔ)法正確性鏡像解析,并最終解析成字典格式
├── database
│?? └── staff_table # 表
├── __init__.py
__init__.py
mysql_run.py # 執(zhí)行程序
github鏈接
程序運(yùn)行命令python mysql_run.py程序正文
mysql_run.py:執(zhí)行腳本
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(): """ 主函數(shù) 獲取用戶輸入,并對(duì)用戶進(jìn)行解析。如果獲取解析值,并執(zhí)行相應(yīng)的sql操作。 """ database_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/database/" # 獲取數(shù)據(jù)庫(kù)文件的路徑 while True: sql_str = input("請(qǐng)輸入sql語(yǔ)句>").strip() if sql_str: sql_type = sql_str.split()[0].lower() # 獲取輸入的sql語(yǔ)句的類型。 if p.parses(sql_type): # 檢查sql的類型是否符合規(guī)則 dict_sql = p.parses(sql_type)(sql_str, sql_type, database_dir) # 調(diào)用parsers模塊的parses函數(shù)進(jìn)行語(yǔ)法解析 if dict_sql: # 如果字典格式的sql語(yǔ)句返回 actions(sql_type)(dict_sql) # 則執(zhí)行后面的sql操作 else: print("sql語(yǔ)法錯(cuò)誤,程序支持select,del,add,update語(yǔ)句。") else: continue
parsers.py:sql語(yǔ)法解析模塊
# -*- coding: utf-8 -*- import re from .help import help def parses(sql_type): """ 語(yǔ)法解析函數(shù) :param sql_type: 從main()函數(shù)導(dǎo)入的sql語(yǔ)句類型。 :return: parsers_dict[sql_type] 相應(yīng)的語(yǔ)法解析函數(shù) """ 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): """ 搜索語(yǔ)句解析函數(shù) :param sql_str: 用戶輸入的sql語(yǔ)句 :param sql_type: 用戶輸入的sql語(yǔ)句類型 :param base_dir: 主函數(shù)導(dǎo)入的數(shù)據(jù)庫(kù)所在路徑 :return: """ dict_sql = {} # 創(chuàng)建空字典 command_parse = re.search(r"selects(.*?)sfroms(.*?)swheres(.*)", sql_str, re.I) # 使用正則表達(dá)式解析add語(yǔ)法,并且re.I忽略大小寫 if command_parse: dict_sql["select"] = command_parse.group(1) dict_sql["from"] = base_dir + command_parse.group(2) # sql字典"from’鍵添加數(shù)據(jù)庫(kù)表文件路徑的值 dict_sql["where"] = command_parse.group(3).split(",") # sql字典‘where’鍵添加插入的值 if logic_cal(dict_sql["where"]): # 使用logic_cal函數(shù)將where語(yǔ)句語(yǔ)法再次進(jìn)行解析 dict_sql["where"] = logic_cal(dict_sql["where"]) # 如解析有返回值,將返回值重新作為dict_sql["where"]的值 return dict_sql else: print(help(sql_type)) # 當(dāng)語(yǔ)法解析不正常答應(yīng)幫助 else: print(help(sql_type)) # 當(dāng)語(yǔ)法解析不正常答應(yīng)幫助 def add_parser(sql_str, sql_type, base_dir): """ 添加語(yǔ)句解析函數(shù) :param sql_str: 用戶輸入的sql語(yǔ)句 :param sql_type: 用戶輸入的sql語(yǔ)句類型 :param base_dir: 主函數(shù)導(dǎo)入的數(shù)據(jù)庫(kù)所在路徑 :return: dict_sql 解析后的字典格式sql語(yǔ)句 """ dict_sql = {} command_parse = re.search(r"addstos(.*?)svaluess(.*)", sql_str, re.I) # 使用正則表達(dá)式解析add語(yǔ)法,并且re.I忽略大小寫 if command_parse: dict_sql["to"] = base_dir + command_parse.group(1) # sql字典"to’鍵添加數(shù)據(jù)庫(kù)表文件路徑的值 dict_sql["values"] = command_parse.group(2).split(",") # sql字典‘values’鍵添加插入的值 return dict_sql else: print(help(sql_type)) # 當(dāng)語(yǔ)法解析不正常答應(yīng)幫助 def del_parser(sql_str, sql_type, base_dir): """ 刪除語(yǔ)句解析函數(shù) :param sql_str: 用戶輸入的sql語(yǔ)句 :param sql_type: 用戶輸入的sql語(yǔ)句類型 :param base_dir: 主函數(shù)導(dǎo)入的數(shù)據(jù)庫(kù)所在路徑 :return: dict_sql 解析后的字典格式sql語(yǔ)句 """ 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’鍵添加數(shù)據(jù)庫(kù)表文件路徑的值 dict_sql["where"] = command_parse.group(2).split(",") # sql字典‘where’鍵添加插入的值 if logic_cal(dict_sql["where"]): # 使用logic_cal函數(shù)將where語(yǔ)句語(yǔ)法再次進(jìn)行解析 dict_sql["where"] = logic_cal(dict_sql["where"]) # 如解析有返回值,將返回值重新作為dict_sql["where"]的值 return dict_sql else: print(help(sql_type)) # 當(dāng)語(yǔ)法解析不正常答應(yīng)幫助 else: print(help(sql_type)) # 當(dāng)語(yǔ)法解析不正常答應(yīng)幫助 def update_parser(sql_str, sql_type, base_dir): """ 更新語(yǔ)句解析函數(shù) :param sql_str: 用戶輸入的sql語(yǔ)句 :param sql_type: 用戶輸入的sql語(yǔ)句類型 :param base_dir: 主函數(shù)導(dǎo)入的數(shù)據(jù)庫(kù)所在路徑 :return: dict_sql 解析后的字典格式sql語(yǔ)句 """ 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’鍵添加數(shù)據(jù)庫(kù)表文件路徑的值 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語(yǔ)句、set語(yǔ)句都符合logic_cal中定義的規(guī)范 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)) # 當(dāng)語(yǔ)法解析不正常答應(yīng)幫助 else: print(help(sql_type)) # 當(dāng)語(yǔ)法解析不正常答應(yīng)幫助 def logic_cal(logic_exp): """ 邏輯函數(shù) :param logic_exp: sql語(yǔ)句中和邏輯判斷相關(guān)的語(yǔ)句,列表格式。如[‘a(chǎn)ge",">=",20] 或 [‘dept","like","HR"] :return: logic_exp 經(jīng)過(guò)語(yǔ)法解析后的邏輯判斷語(yǔ)句。列表格式。如[‘a(chǎn)ge","==",20] 或 [‘dept","like","HR"] """ # 表達(dá)式列表優(yōu)化成三個(gè)元素,形如[‘a(chǎn)ge",">=",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匹配的所有值,并作為一個(gè)列表 if logic_exp[1] == "=": logic_exp[1] = "==" # 判斷邏輯運(yùn)算的比較符號(hào)后的值是否字母,并且用戶是否輸入了雙引號(hào)。如沒(méi)有輸入手工添加上雙引號(hào)。 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操作主函數(shù) :param sql_type: sql語(yǔ)句的類型 :return: actions_dict[sql_type] 相應(yīng)操作的函數(shù) """ actions_dict = {"select": select_action, "add": add_action, "del": del_action, "update": update_action} if sql_type in actions_dict: # 判斷導(dǎo)入的sql類型是否在actions_dict字典中定義。 return actions_dict[sql_type] def select_action(dict_sql): info = dict_sql["select"] data = read_db(dict_sql["from"]) # 獲取原始數(shù)據(jù)庫(kù)文件中的所有數(shù)據(jù),data為列表格式 key = dict_sql["where"][0] # 獲取sql語(yǔ)句中where語(yǔ)句的key值。如id = 1,獲取id count = 0 for values in data: # 讀取data列表中的每一個(gè)元素,values是字典格式 if type(values[key]) is int: value = str(values[key]) else: value = """ + str(values[key]) + """ dict_sql["where"][0] = value # 將values[key]的值取出并重新賦值為sql語(yǔ)句的key值。 if where_action(dict_sql["where"]): # 將新的where語(yǔ)句,發(fā)送給where_action語(yǔ)句進(jìn)行bool判斷。 count += 1 print_info(info, **values) print("已查找%s條記錄" % count) def add_action(dict_sql): """ 插入動(dòng)作 獲取用戶輸入的values,并在表中插入 :param dict_sql: parsers函數(shù)處理后的字典格式的sql語(yǔ)句 """ data = read_db(dict_sql["to"]) # 獲取原始數(shù)據(jù)庫(kù)文件中的所有數(shù)據(jù) value = dict_sql["values"] # 從dict_sql中獲取values的列表 t_id = str(int(data[-1]["id"]) + 1) # 獲取原始數(shù)據(jù)庫(kù)文件中id列最后一行的id數(shù)值,并每次自動(dòng)+1。然后轉(zhuǎn)換為字符串格式 value.insert(0, t_id) # 將添加的id插入到value變量中 if len(value) != len(get_title()): # 判斷輸入值得長(zhǎng)度是否等于數(shù)據(jù)庫(kù)文件中定義的列的長(zhǎng)度 print("列數(shù)不正確") else: data.append(dict(zip(get_title(), value))) # 在獲取的原始數(shù)據(jù)中插入行的數(shù)據(jù) print("已添加記錄") write_db(dict_sql["to"], data) # 寫入文件 def del_action(dict_sql): """ 刪除動(dòng)作函數(shù) :param dict_sql: parsers函數(shù)處理后的字典格式的sql語(yǔ)句 """ temp_list = [] data = read_db(dict_sql["from"]) # 獲取原始數(shù)據(jù)庫(kù)文件中的所有數(shù)據(jù),data為列表格式 key = dict_sql["where"][0] # 獲取sql語(yǔ)句中where語(yǔ)句的key值。如id = 1,獲取id for values in data: # 讀取data列表中的每一個(gè)元素,values是字典格式 if type(values[key]) is int: value = str(values[key]) else: value = """ + str(values[key]) + """ dict_sql["where"][0] = value # 將values[key]的值取出并重新賦值為sql語(yǔ)句的key值。 if where_action(dict_sql["where"]): # 將新的where語(yǔ)句,發(fā)送給where_action語(yǔ)句進(jìn)行bool判斷。 temp_list.append(values) # 如果符合條件,就從data中移除對(duì)應(yīng)的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): """ 更新動(dòng)作函數(shù) :param dict_sql: parsers函數(shù)處理后的字典格式的sql語(yǔ)句 """ data = read_db(dict_sql["update"]) # 獲取原始數(shù)據(jù)庫(kù)文件中的所有數(shù)據(jù),data為列表格式 key = dict_sql["where"][0] # 獲取sql語(yǔ)句中where語(yǔ)句的key值。如id = 1,獲取id set_key = dict_sql["set"][0] # 獲取set語(yǔ)句中用戶輸入的key set_value = dict_sql["set"][3].strip(""").strip(""") # 獲取set語(yǔ)句中用戶輸入的value count = 0 for values in data: # 讀取data列表中的每一個(gè)元素,values是字典格式 if type(values[key]) is int: value = str(values[key]) else: value = """ + str(values[key]) + """ dict_sql["where"][0] = value # 將values[key]的值取出并重新賦值為sql語(yǔ)句的key值。 if where_action(dict_sql["where"]): # 將新的where語(yǔ)句,發(fā)送給where_action語(yǔ)句進(jìn)行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語(yǔ)句操作函數(shù) :param condition: 判斷語(yǔ)句。就是字典中where的值 :return: """ if "like" in condition: # 如果like在語(yǔ)句中 # 將where語(yǔ)句中的第二個(gè)參數(shù)和,第一個(gè)參數(shù)進(jìn)行正則比較。如果執(zhí)行正常就返回True return re.search(condition[2].strip(""").strip("""), condition[0]) and True else: return eval(" ".join(condition)) # 除此使用eval進(jìn)行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語(yǔ)法錯(cuò)誤。請(qǐng)查看案例: 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語(yǔ)法錯(cuò)誤。請(qǐng)查看案例: add to staff_table values Alex Li,25,134435344,IT,2015-10-29 """ return strings def del_help(): strings = """del語(yǔ)法錯(cuò)誤。請(qǐng)查看案例: del from staff_table where id = 3 """ return strings def update_help(): strings = """update語(yǔ)法錯(cuò)誤。請(qǐng)查看案例: 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): """ 讀取表文件函數(shù)。 :param table: 表文件參數(shù) :return: 返回一個(gè)包含表文件內(nèi)容的字典 """ 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): """ 寫入表文件函數(shù)。 :param table: 表文件參數(shù) :param data: 導(dǎo)入的數(shù)據(jù)。為字典格式 """ 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): """ 打印函數(shù)。 用于select語(yǔ)句打印顯示 :param info: select語(yǔ)句中需要顯示的類 :param kwargs: 字典,用于進(jìn)行操作的原始數(shù)據(jù) :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
學(xué)習(xí)筆記文件處理筆記
函數(shù)基礎(chǔ)筆記
函數(shù)高階筆記
模塊筆記(待修改)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/44562.html
摘要:如果初學(xué)者接觸的第一門語(yǔ)言是,學(xué)習(xí)曲線則會(huì)平滑得多,掌握一些基本語(yǔ)法和內(nèi)置的數(shù)據(jù)結(jié)構(gòu),已經(jīng)可以上手寫一些小工具或者小型應(yīng)用。如果你的學(xué)習(xí)時(shí)間充足,我的建議是一定要學(xué)數(shù)據(jù)結(jié)構(gòu)和算法。 前言 Python是最容易入門的編程語(yǔ)言,沒(méi)有之一。如果初學(xué)者接觸的第一門語(yǔ)言是C或者C++,對(duì)他們來(lái)說(shuō)最難的不是語(yǔ)法,而是容易出現(xiàn)內(nèi)存泄漏、指針等問(wèn)題。有時(shí)候排查這些問(wèn)題對(duì)初學(xué)者的打擊很大,尤其是沒(méi)掌握排...
摘要:所以就找外包公司,找到一個(gè)有經(jīng)驗(yàn)的程序員來(lái)做,這樣做既可以保證質(zhì)量,有可以跟上進(jìn)度。為什么不建議去外包為什么不要去外包公司總體原因如下沒(méi)有歸屬感想想工作周圍大部分不是自己的同事,想找人說(shuō)個(gè)話都難。 前言 最近有好多人討論外包,前幾天看到一個(gè)帖子說(shuō)就是有一個(gè)外包吃了公司的的零食,遭到HR當(dāng)場(chǎng)批評(píng), 搞的整個(gè)IT界備受關(guān)注,那么外包公司和非外包公司有什么樣的不一樣呢?我今天也說(shuō)說(shuō)我的看法! ...
摘要:表示需要攔截的請(qǐng)求類型。表示數(shù)據(jù)模板,可以是對(duì)象或字符串。表示用于生成響應(yīng)數(shù)據(jù)的函數(shù)。指向本次請(qǐng)求的選項(xiàng)集。生成規(guī)則是可選的。返回成功的數(shù)據(jù),就是登錄成功了,否則相反。模擬登錄接下來(lái)介紹模擬表格增刪改查。 前言 關(guān)于mockjs,官網(wǎng)描述的是 1.前后端分離 2.不需要修改既有代碼,就可以攔截 Ajax 請(qǐng)求,返回模擬的響應(yīng)數(shù)據(jù)。 3.數(shù)據(jù)類型豐富 4.通過(guò)隨機(jī)數(shù)據(jù),模擬各種場(chǎng)景。 5...
?程序員小王的博客:程序員小王的博客 ? 歡迎點(diǎn)贊 ? 收藏 ?留言 ? ? 如有編輯錯(cuò)誤聯(lián)系作者,如果有比較好的文章歡迎分享給我,我會(huì)取其精華去其糟粕 ?java自學(xué)的學(xué)習(xí)路線:java自學(xué)的學(xué)習(xí)路線 一、員工管理系統(tǒng)項(xiàng)目說(shuō)明: 該項(xiàng)目主要是完成Spring+SpringMVC+mybatis的完整整合,功能實(shí)現(xiàn)比較單一,就是一個(gè)完成增刪改查的小項(xiàng)目! 源代碼在githee倉(cāng)庫(kù):SSM實(shí)戰(zhàn)項(xiàng)目...
閱讀 917·2021-11-08 13:22
閱讀 2841·2021-09-29 09:45
閱讀 2824·2021-09-09 11:52
閱讀 2257·2019-08-30 13:20
閱讀 3740·2019-08-29 13:28
閱讀 1356·2019-08-29 12:32
閱讀 2720·2019-08-29 11:10
閱讀 1644·2019-08-26 13:34