要求,通过文件读写实现增删改查
global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defaults log global mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms option dontlognull listen stats :8888 stats enable stats uri /admin stats auth admin:1234 frontend oldboy.org bind 0.0.0.0:80 option httplog option httpclose option forwardfor log global acl www hdr_reg(host) -i www.oldboy.org use_backend www.oldboy.org if www backend www.oldboy.org server 100.1.7.9 weight 20 maxconn 30 backend www.sina.com server 100.1.7.7 100.1.7.7 weight 20 maxconn 3000 backend www.baidu.com server 100.1.7.9 weight 20 maxconn 30
以上是配置文件内容。
1 import os 2 # 导入os模块,获得haproxy.txt的路径 3 DB_PATH=os.path.join(os.path.dirname(__file__),"haproxy.txt") 4 # 获得new.txt的路径,这是一个临时文件,用于临时存需要修改的数据,之后会改名成haproxy.txt,而之前的haproxy.txt文件将会被删除 5 DB_NEW_PATH=os.path.join(os.path.dirname(__file__),"new.txt") 6 7 # 查找函数(查询函数中调用的) 8 def select(bef_find): 9 with open(DB_PATH, "r", encoding="utf-8")as f: 10 # 每行每行的遍历。防止文件过大 爆内存 11 for line in f: 12 # 查询到一样的字符串 就读取它的下一行。然后返回 13 if bef_find == line: 14 out_find = f.readline() 15 return out_find 16 # 若读完全部的行后都没找到打印该信息 17 else: 18 print("没有查询到") 19 20 # 添加消息函数 21 def add_message(one_line): 22 with open(DB_PATH,'a',encoding="utf-8")as f: 23 f.write(one_line) 24 25 def update_message(old_data,new_data): 26 # 方法都一样。 27 with open(DB_PATH,"r",encoding="utf-8")as f, 28 open(DB_NEW_PATH,"w",encoding="utf-8")as f1: 29 for line in f: 30 if line == old_data: 31 line=line.replace(line,new_data) # 因为字符串是不可变类型,所以要重新进行赋值才能实现修改操作 32 f1.write(line) 33 os.remove(DB_PATH) 34 os.rename(DB_NEW_PATH,DB_PATH) 35 36 # 查询函数 37 def search(): 38 while True: 39 # 接受查询的网址 40 find=input("请输入查询的网址:") 41 if find=="q": 42 break 43 # 设置开头,拼接成查询的数据的最终格式 44 before="backend " 45 bef_find=before+find+" " 46 # 调用查找函数 47 res=select(bef_find) 48 # 若查找函数没有返回值就什么都不做 49 if not res: 50 pass 51 # 若查找函数有返回值,打印它 52 else: 53 print(res) 54 55 # 添加函数 56 def add(): 57 while True: 58 # 接收记录 59 args=input("请输入添加的记录(以字典的形式):").strip() 60 # 接收到 q 退出 61 if args=='q': 62 break 63 '''arg = {'backend': 'www.oldboy.org','record': {'server': '100.1.7.9','weight': 20,'maxconn': 30}}''' 64 # 如果输入正确,是能够调用eval函数不报错的进入try的函数 65 try: 66 # 执行eval内置函数,将字符串转换成python类型 67 args=eval(args) 68 # 拼接字符串 69 bef_find = f"backend " + args["backend"] + " " 70 # 调用查询函数,接收返回值 71 old_data = select(bef_find) 72 # 有返回值,打印”已经存在了“ 73 if old_data: 74 print("已经存在了,不能添加该网址的配置") 75 break 76 # 没有返回值就继续拼接字符串 77 one_line = f"backend {args['backend']} server {args['record']['server']} weight {args['record']['weight']} maxconn {args['record']['maxconn']} " 78 # 调用添加消息函数。 79 add_message(one_line) 80 # 否则就抛出异常 81 except (SyntaxError,TypeError,KeyError,NameError,UnboundLocalError): 82 print("输入格式不符合规范") 83 84 85 86 87 def update(): 88 while True: 89 # 还是接收记录 90 args=input("请输入要更新的记录(以字典的形式):").strip() 91 if args=="q": 92 break 93 # 都跟删除的一样的套路 94 try: 95 args = eval(args) 96 # 拼接字典的值 97 bef_find=f"backend "+ args["backend"] +" " 98 # 调用查找函数 99 old_data=select(bef_find) 100 '''arg = {'backend': 'www.oldboy.org','record': {'server': '100.1.7.9','weight': 20,'maxconn': 30}}''' 101 # 继续拼接字符串 102 new_data=f" server {args['record']['server']} weight {args['record']['weight']} maxconn {args['record']['maxconn']} " 103 # 调用更新记录函数,将老数据和新数据传进去 104 update_message(old_data,new_data) 105 except (SyntaxError,TypeError,KeyError,NameError,UnboundLocalError): 106 print("输入格式不符合规范") 107 108 109 def delete(): 110 while True: 111 # 接收网址 112 website=input("请输入要删除的网址:").strip() 113 # q就退出 114 if website=="q": 115 break 116 # 创建一个旗帜,默认为False,通过旗帜来控制是否将haproxy.txt的内容是否写入到new.txt的文件中(最后通过改名变相的起到了删除的作用) 117 delete_flag=False 118 # 计数,删除多少条(貌似没啥子用) 119 count=0 120 # 用读方式打开,haproxy.txt, 用写的方式打开new.txt(w方式下没有就会新建一个空文件) 121 with open(DB_PATH,"r",encoding="utf-8")as f, 122 open(DB_NEW_PATH,"w",encoding="utf-8")as f1: 123 # 还是遍历每一行,免得爆内存 124 for line in f: 125 # 还是老办法,继续拼接字符串 126 if f"backend {website}" == line.strip(): 127 # 若相等,就将旗帜设置为True(之后判断是否写入到new文件中的时候,True就表示不写) 128 delete_flag=True 129 count+=1 130 continue 131 # 遍历到下一行的时候,碰到backend开头的字符串,并且 后面的网址不存在的就把旗帜给调会False(不恢复的话后面的都不会写入new文件) 132 if line.strip().startswith("backend") and line.strip()!=website.strip(): 133 delete_flag=False 134 # 旗帜为False 就写写写 135 if not delete_flag: 136 f1.write(line) 137 print(f"找到{count}条,已经删除!") 138 # 移除之前的文档,把新文档改名成老文档,实现删除功能 139 os.remove(DB_PATH) 140 os.rename(DB_NEW_PATH,DB_PATH) 141 142 # 创建一个功能字典,用于存放【功能编号】 和 【函数地址】 143 run_dict={ 144 "1":search, 145 "2":add, 146 "3":update, 147 "4":delete, 148 } 149 def run(): 150 while True: 151 # 遍历功能字典,取出函数名称 152 for k in run_dict: 153 print(k,run_dict[k].__name__) 154 # 获取功能编号 155 choice=input("请输入功能:").strip() 156 # 接收到q就退出 157 if choice=="q": 158 break 159 # 查看是否是数字 160 if not choice.isdigit(): 161 print("您输入的不是数字!") 162 continue 163 # 查看是否有这个功能编号 164 if choice not in run_dict.keys(): 165 print("没有该功能编码!") 166 continue 167 # 通过功能编号调用对应的函数 168 run_dict[choice]() 169 170 run()