#1.查找:从文件中找到www.oldboy1.org对应的backend记录并打印出相应的backend块 ##################文件haproxy.conf中某个backend段落########################## backend www.oldboy1.org server 101.1000.7.9 101.1000.7.9 weight 20 maxconn 30 server 2.2.2.7 2.2.2.7 weight 30 maxconn 4000 server 10.10.10.1 10.10.10.1 weight 22 maxconn 2000 server 2.2.2.5 2.2.2.5 weight 30 maxconn 4000 ############################################################## import os # 程序的解耦: 把fetch和change的文件处理部分都合并到一起。一起来处理。增加代码可读性(注意函数的参数要传完整) def file_handler(backend_data,res=None,type='fetch'): #fetch就可以不传res和type了 if type == 'fetch': #查询功能 with open('haproxy.conf','r') as read_f: tag=False #如果没被改,那完全没有必要管它 ret=[] #为了使得fetch函数能够被别的功能调用。利用fetch函数返回值来给别的函数调用,用一个空列表存fetch查到的backend块 for read_line in read_f: if read_line.strip() == backend_data: #找到了,将tag变true #strip()默认去掉每行收尾的回车和空格。括号内可以注明专门想要去什么。 tag=True #test.py文件中补充tag的用法 continue if tag and read_line.startswith('backend'): #tag为true且遍历完一个backend段落 #haproxy.conf文件中遍历完一个之后将再次出现backend,因此可以把它作为条件 # tag=False #for循环还会继续,终止不了for循环,不如直接用break break #找着了而且遍历完了一个backend块 if tag: print('\033[1;45m%s\033[0m' %read_line,end='') #end=''用于去掉打印是每行记录后面出现的换行 #每找到一个backend块www.oldboy1.org,就将它的信息一条一条地打印出来了, ret.append(read_line) #加入到ret列表当中,存起来最终作为fetch函数的返回值 return ret elif type == 'change': with open('haproxy.conf', 'r') as read_f, \ open('haproxy.conf_new', 'w') as write_f: #不能与源文件同名,否则以写的方式打开,原文件直接被清空,还没来得及读 tag = False #tag为true相当于遇到需要修改的内容了。 has_write = False # for read_line in read_f: if read_line.strip() == backend_data: #与change函数中拼接内容对比 # 只匹配backend 主机名(所以此句只会匹配成功一次并将tag改为true) tag = True #当tag为True之后,只要没读完本backend的内容,就会进入第三个if对应的else当中, continue #直接进入下一次循环,即下一次开始就再也不会执行此if语句了 if tag and read_line.startswith('backend'): #标识下一个backend则应该关闭tag # tag为true且遍历完一个backend段落,遇到下一个主机名的backend tag = False #不能break if not tag: #读一行写一行,没有遇到要求修改的,直接将不改的写入 write_f.write(read_line) else: #读到需要修改的内容了,将新的record写入新文件(这里只写入了所有sever,没有写backend www.oldboy1.com),因为这句话进来时在第一个if中被continue掉了 if not has_write: #如果不加这个,有一个server就会写一遍backend,这样会新增好几条oldboy1的backend记录 for record in res: #把新记录中的所有sever全部写出来 write_f.write(record) #列表中只有sever信息,因为找到时在第一个if中tag=true后就直接continue了 has_write = True #标识已经写完一遍修改后的backend,否则下一个sever进来又会将整个正确的backend块再写一遍 # 新文件覆盖掉源文件 。改的是文件名,字符串没有任何变化 os.rename('haproxy.conf', 'haproxy.conf.bak') #原来文件改名成后一项名字 os.rename('haproxy.conf_new', 'haproxy.conf') #新的文件覆盖到初始文件名对应的文件 os.remove('haproxy.conf.bak') #删除临时文件,haproxy.conf_new依旧存在,可以不用删除 def fetch(data): print('\033[1;43m这是查询功能\033[0m') #\033加颜色 print('\033[1;43m用户数据是\033[0m',data) backend_data='backend %s' %data return file_handler(backend_data) #调用file handler函数 def add(): pass def change(data): #输入data所以形参也要加上data # print('这是修改功能') # print('用户输入的数据是',data) #输入为字典形式:第一个:需要修改哪一个记录;第二个要改成什么样子的记录 # [{'backend':'www.oldboy1.org','record':{'server':'2.2.2.4','weight':20,'maxconn':3000}}, # {'backend':'www.oldboy1.org','record':{'server':'2.2.2.5','weight':30,'maxconn':4000}}] backend=data[0]['backend'] #此句只取了一个主机名字 #提取出输入的想要修改的文件当中的一条记录 www.oldboy1.org 列表的第0编号中字典的‘backend’关键字对应的 # 用户输入的是字符串记得送入函数之前,即用户一输入data,就应该把data利用eval转化为 backend_data='backend %s' %backend #将主机名前面补全成系统文件中格式: backend www.oldboy1.org # server 2.2.2.4 2.2.2.4 weight 20 maxconn 3000 #列表中每行都有一个换行符\n别忘记了,否则无法匹配 old_server_record='%sserver %s %s weight %s maxconn %s\n' %(' '*8,data[0]['record']['server'], #空格乘以8,表示开头有八个空格 data[0]['record']['server'], data[0]['record']['weight'], data[0]['record']['maxconn']) new_server_record = '%sserver %s %s weight %s maxconn %s\n' % (' ' * 8, data[1]['record']['server'], data[1]['record']['server'], data[1]['record']['weight'], data[1]['record']['maxconn']) print('用户想要修改的记录是',old_server_record) res=fetch(backend) #fetch('www.oldboy1.org')判断你要改的记录在不在文件中。res为backend块除头部的全部内容 print('来自change函数--》',res) #调用fetch函数,返回了res的数值 if not res or old_server_record not in res: return '你要修改的记录不存在' else: index=res.index(old_server_record) #取出要修改文件的索引 res[index]=new_server_record #在新的列表res中将相应待修改位置的元素放入新的数值 #注意:列表是可以修改的,但文件只能通过覆盖的方式 res.insert(0,'%s\n' %backend_data) #在写入文件之前提前在res中写入待修改的backend行, 用insert加在最前面不要用append #从而对应利用backend信息修改tag为true之后直接continue,就不用写入backend www.oldboy1.com语句了 file_handler(backend_data,res=res,type='change') def delete(): pass # print(_name_) #__main__ 说明如果系统变量_name_的值就是'__main__'。 #当你把python文件直接当做一个脚本,非模块(一个单独的程序去运行时)有这个等式成立:__name__ = '__main__' #下面是测试代码。一般下python文件只写各种功能便于别人调用 if __name__ == '__main__': msg=''' 1:查询 2:添加 3:修改 4:删除 5:退出 ''' #对于修改功能:先要检索用户想要修改的记录是否在列表中,如果在才能修改。因此fetch查询功能在别的功能里也会用到。 msg_dic={ #函数字典,用户输入对应的函数编号,就能通过下方代码匹配到相应的函数密码检测名称,从而调用函数 '1':fetch, #此处只写函数名,不加() '2':add, '3':change, '4':delete, } # 5:可以不写 ‘5’=exit直接用break来在循环中实现 while True: print(msg) choice=input('请输入你的选项:').strip() #去掉数据中的空格和换行符 if not choice:continue if choice == '5':break data=input('请输入你的数据:').strip() #选择后进一步的数据操作 if choice != '1': #2,3,4都非查询,需要修改数据类型 data=eval(data) #eval可以提取字符串中的数据运算一遍,或者提取数据结构:'' #eval不能操作一个字符串,例如‘advduhvih’传入eval中就会报错 res=msg_dic[choice](data) #根据choice的编号在函数字典中找到对应的函数名,从而调用函数 # 并把data作为参数放在在括号中,输入给函数 print('最终结果是--》',res) #打印出一条条server,backend #修改模式下传入的待修改记录:# >>>[{'backend':'www.oldboy1.org','record':{'server':'2.2.2.4','weight':20,'maxconn':3000}},{'backend':'www.oldboy1.org','record':{'server':'2.2.2.5','weight':30,'maxconn':4000}}]
二、 tag的用法
# tag的用法 # 为了能在下一层成功跳转到上一层去用break # 如果执行一个quit_all,就能退出所有循环,利用一个状态tag来标识所有所有都是 tag=True while tag: print('leve1') choice=input("level1>>: ").strip() if choice == 'quit':break if choice == 'quit_all': tag = False while tag: print('level2') choice = input("level2>>: ").strip() if choice == 'quit': break if choice == 'quit_all': tag = False while tag: print('level3') choice = input("level3>: ").strip() if choice == 'quit': break if choice == 'quit_all': tag = False import os # os.rename('a.txt','a.txt.bak') os.rename('b.txyt','a.txt')