A trick to exit the three-level cycle directly:

tag = True
while tag:
    print('level1')
    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

There is a file called haproxy.conf, the content of which is as follows:

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.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

backend www.oldboy2.org
        server 3.3.3.3 3.3.3.3 weight 20 maxconn 3000
backend www.oldboy20.org
        server 10.10.0.10 10.10.0.10 weight 9999 maxconn 33333333333


Write a query function for this file:

def fetch(data):
    print('\033[1;43m This is the query function!\033[0m')   #The color here doesn't show up in my pycharm. Why???
    print('\033[1;43m User data is\033[0m',data)
    backend_data='backend %s\n' %data   #If you don't add \ n here, it's OK to add strip() below
    with open('haproxy.conf','r') as read_f:
        tag=False
        ret = []
        for read_line in read_f:
            if read_line == backend_data:   #read_line.strip() removes the carriage return after a sentence. By default, strip is used to remove spaces and carriage returns at the beginning and end of a string, and also to remove specified symbols.
                tag=True   #Alarm rings, next line of data needs to be output
                continue  #Go directly to the next cycle
            if tag:   #Write as if tag and read_line. Startswitch ('backend '): break can also
                if read_line.startswith('backend'):   #Judge whether the start is backend on the basis that the tag is equal to True
                    # tag=False  #No need to change to False
                    break
            if tag:
                print(read_line,end='') #end = '' causes the function to turn off the default behavior of automatically include line breaks in output
                ret.append(read_line)
    return ret

def add():
    pass

def change():
    pass

def delete():
    pass

if __name__ =='__main__' :
    msg='''
    1: query
    2: Add to
    3: modify
    4: delete
    5: Sign out
    '''
    msg_dic={
        '1':fetch,
        '2':add,
        '3':change,
        '4':delete,
        '5':exit
    }
    while True:
        print(msg)
        choice=input('Please enter your options:').strip()
        if not choice:continue    #choice has its own Boolean value. If it is empty, it returns False.
        if choice == '5':break

        data = input('Please input your data').strip()
        res = msg_dic[choice](data)
        print(res)

Add: the role of eval function:

print(type(eval('[1,2,3,4]')))  #<class 'list'>
print(type(eval('1+3')))  #<class 'int'>
print(type(eval('abc')))  #Error reporting (eval cannot be used for string)

Write modification function for this file:

import os
def fetch(data):
    # print('\033[1;43m This is the query function!\033[0m')   #The color here doesn't show up in my pycharm. Why???
    # print('3[1;43m user data is \ 033[0m',data)
    backend_data='backend %s\n' %data   #If you don't add \ n here, it's OK to add strip() below
    with open('haproxy.conf','r') as read_f:
        tag=False
        ret = []
        for read_line in read_f:
            if read_line == backend_data:   #read_line.strip() removes the carriage return after a sentence. By default, strip is used to remove spaces and carriage returns at the beginning and end of a string, and also to remove specified symbols.
                tag=True   #Alarm rings, next line of data needs to be output
                continue  #Go directly to the next cycle
            if tag:   #Write as if tag and read_line. Startswitch ('backend '): break can also
                if read_line.startswith('backend'):   #Judge whether the start is backend on the basis that the tag is equal to True
                    # tag=False  #No need to change to False
                    break
            if tag:
                print(read_line,end='') #end = '' causes the function to turn off the default behavior of automatically include line breaks in output
                ret.append(read_line)
    return ret

def add():
    pass

def change(data):
    # print('This is a modification function ')
    # print('the data entered by the user is: ', data)
    backend=data[0]['backend'] #A record in the document www.oldby1.org
    backend_data='backend %s' %backend  #backend www.oldboy1.org
    #Splicing user input data into a document format
    old_server_record='%sserver %s %s weight %s maxconn %s\n' %(' '*8,data[0]['record']['server'],    #Don't forget \ n
                                                              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('The original record that the user wants to modify is>>>',old_server_record)
    res = fetch(backend)
    print('Come from change function>>>',res)
    if not res or old_server_record not in res:   #If an empty list is returned or the data the user is looking for is not in the dataset
        return 'The record you want to modify does not exist'
    else:
        index=res.index(old_server_record)  # Find the index of this record in the list
        res[index]=new_server_record
        print('Value in list modified')
    #Then start the file processing (the file has not been modified, only write a new file, delete the old file)
    res.insert(0,'%s\n' %backend_data)
    with open('haproxy.conf','r') as read_f,\
            open('haproxy.conf_new','w') as write_f:
        tag=False
        has_written=False
        for read_line in read_f:
            if read_line.strip() == backend_data:
                tag=True  #Sounding the alarm
                continue
            if tag and read_line.startswith('backend'):   #Turn off the alarm (note that the tag=True condition must be added)
                tag = False
            if not tag:
                write_f.write(read_line)
            else:
                if not has_written:
                    for record in res:
                        write_f.write(record)
                    has_written=True
    os.rename('haproxy.conf','haproxy.conf.bak')  #Change the name of the file called haproxy.conf to haproxy.conf.bak
    os.rename('haproxy.conf_new', 'haproxy.conf')
    os.remove('haproxy.conf.bak')


def delete():
    pass

if __name__ =='__main__' :
    msg='''
    1: query
    2: Add to
    3: modify
    4: delete
    5: Sign out
    '''
    msg_dic={
        '1':fetch,
        '2':add,
        '3':change,
        '4':delete,
        '5':exit
    }
    while True:
        print(msg)
        choice=input('Please enter your options:').strip()
        if not choice:continue    #choice has its own Boolean value. If it is empty, it returns False.
        if choice == '5':break

        data = input('Please input your data').strip()  #Note: even if the input is a list, the input receives a string
        if choice !='1':  #Because the user entered a string
            data = eval(data)
        res = msg_dic[choice](data)
        print(res)

#[{'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}}]

It can be found that there are duplicate statements about file processing in query and modification functions, so a new function can be created specifically to include the statements of file processing to enhance the readability of the program.

Episode:

When you enter the following code, it does not work properly:
[{'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}}]


It works when you enter the following code
[{'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}}]

(it should be whether there is a return problem)

Program decoupling

import os
def fetch(data):
    # print('\033[1;43m This is the query function!\033[0m')   #The color here doesn't show up in my pycharm. Why???
    # print('3[1;43m user data is \ 033[0m',data)
    backend_data='backend %s\n' %data   #If you don't add \ n here, it's OK to add strip() below
    with open('haproxy.conf','r') as read_f:
        tag=False
        ret = []
        for read_line in read_f:
            if read_line == backend_data:   #read_line.strip() removes the carriage return after a sentence. By default, strip is used to remove spaces and carriage returns at the beginning and end of a string, and also to remove specified symbols.
                tag=True   #Alarm rings, next line of data needs to be output
                continue  #Go directly to the next cycle
            if tag:   #Write as if tag and read_line. Startswitch ('backend '): break can also
                if read_line.startswith('backend'):   #Judge whether the start is backend on the basis that the tag is equal to True
                    # tag=False  #No need to change to False
                    break
            if tag:
                print(read_line,end='') #end = '' causes the function to turn off the default behavior of automatically include line breaks in output
                ret.append(read_line)
    return ret

def add():
    pass

def change(data):
    # print('This is a modification function ')
    # print('the data entered by the user is: ', data)
    backend=data[0]['backend'] #A record in the document www.oldby1.org
    backend_data='backend %s' %backend  #backend www.oldboy1.org
    #Splicing user input data into a document format
    old_server_record='%sserver %s %s weight %s maxconn %s\n' %(' '*8,data[0]['record']['server'],    #Don't forget \ n
                                                              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('The original record that the user wants to modify is>>>',old_server_record)
    res = fetch(backend)
    print('Come from change function>>>',res)
    if not res or old_server_record not in res:   #If an empty list is returned or the data the user is looking for is not in the dataset
        return 'The record you want to modify does not exist'
    else:
        index=res.index(old_server_record)  # Find the index of this record in the list
        res[index]=new_server_record
        print('Value in list modified')
    #Then start the file processing (the file has not been modified, only write a new file, delete the old file)
    res.insert(0,'%s\n' %backend_data)
    with open('haproxy.conf','r') as read_f,\
            open('haproxy.conf_new','w') as write_f:
        tag=False
        has_written=False
        for read_line in read_f:
            if read_line.strip() == backend_data:
                tag=True  #Sounding the alarm
                continue
            if tag and read_line.startswith('backend'):   #Turn off the alarm (note that the tag=True condition must be added)
                tag = False
            if not tag:
                write_f.write(read_line)
            else:
                if not has_written:
                    for record in res:
                        write_f.write(record)
                    has_written=True
    os.rename('haproxy.conf','haproxy.conf.bak')  #Change the name of the file called haproxy.conf to haproxy.conf.bak
    os.rename('haproxy.conf_new', 'haproxy.conf')
    os.remove('haproxy.conf.bak')


def delete():
    pass

if __name__ =='__main__' :
    msg='''
    1: query
    2: Add to
    3: modify
    4: delete
    5: Sign out
    '''
    msg_dic={
        '1':fetch,
        '2':add,
        '3':change,
        '4':delete,
        '5':exit
    }
    while True:
        print(msg)
        choice=input('Please enter your options:').strip()
        if not choice:continue    #choice has its own Boolean value. If it is empty, it returns False.
        if choice == '5':break

        data = input('Please input your data').strip()  #Note: even if the input is a list, the input receives a string
        if choice !='1':  #Because the user entered a string
            data = eval(data)
        res = msg_dic[choice](data)
        print(res)

#[{'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}}]