文件的查询、修改实例+tag的用法++函数+程序的解耦

#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('33[1;45m%s33[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('33[1;43m这是查询功能33[0m')                #33加颜色
    print('33[1;43m用户数据是33[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

    #列表中每行都有一个换行符
别忘记了,否则无法匹配
    old_server_record='%sserver %s %s weight %s maxconn %s
' %(' '*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
' % (' ' * 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
' %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')
原文地址:https://www.cnblogs.com/Josie-chen/p/8716329.html