Search code examples
pythonautomationprogress-barcisconetmiko

Progress bar in Netmiko's send_config_set()


I would like to add a progress bar in my Python script on send_config_set(rendered_template,cmd_verify=False). That rendered_template is generated dynamically so it could vary in size and no. of commands can also be changes. How to add a progress bar so that I can show progress for send_config_set() command. Below is the code which I tried

animation = "|/-\\"            
for i in range(nlines):
    device_handler.send_config_set(rendered_template,cmd_verify=False)
    time.sleep(0.1)
    sys.stdout.write("\r" + animation[i % len(animation)])
    sys.stdout.flush()
print ("End!")

it first executes the command without showing progress bar and when command executed then it is showing progress bar.

Seeking Help!!

Thanks!


Solution

  • I think you should end flushing by sending sys.stdout.write("]\n") after the loop ends.

    animation = "|/-\\"            
    for i in range(nlines):
        device_handler.send_config_set(rendered_template,cmd_verify=False)
        time.sleep(0.1)
        sys.stdout.write("\r" + animation[i % len(animation)])
        sys.stdout.flush()
    sys.stdout.write("]\n")  # this ends the progress bar
    print ("End!")
    

    This answer should perfectly fit your case.

    The progressbar in your code is not really a progressbar, because commands are sent through send_config_set() which should be completed first, then the sys.stdout.write("\r" + animation[i % len(animation)]) is executed. Also, using send_config_set sends the commands multiple times (based on the nlines value) because it's within a "for loop"! You can send commands one by one using send_command or send_command_timing.

    Please check tqdm, it's an extensible progressbar library for Python that would be very useful.

    Using tqdm is pretty straightforward. A complete demo using tqdm with Netmiko:

    from netmiko import ConnectHandler
    from tqdm import tqdm
    
    device = {
        "device_type": "cisco_ios",
        "ip": "",
        "username": "",
        "password": "",
        "session_log": "whatever.log",
    }
    
    rendered_template = ["show ip interface brief", "show running-config", "show inventory"]
    nlines = len(rendered_template)
    
    with ConnectHandler(**device) as net_connect:
        for i in tqdm(range(nlines), unit="command", desc="show commands"):
            output = net_connect.send_command_timing(rendered_template[i], cmd_verify=False)
    print("Done!")
    

    or use a list comprehension if output is not necessary to be returned.

    with ConnectHandler(**device) as net_connect:
        # List comprehension
        [
            net_connect.send_command_timing(rendered_template[i], cmd_verify=False)
            for i in tqdm(range(nlines), unit="command", desc="show commands")
        ]
    

    Output

    show commands: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:12<00:00,  4.26s/command]
    Done!
    

    Update August 17th, 2023

    netmiko==4.2.0 and tqdm==4.66.1

    rendered_template = ["show ip interface brief", "show running-config", "show inventory"]
    
    with ConnectHandler(**device) as net_connect:
        for command in tqdm(iterable=rendered_template, unit="command", desc="show commands"):
            output = net_connect.send_command(command, cmd_verify=False, read_timeout=60)
    print("Done!")
    
    show commands: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████| 20/20 [01:10<00:00,  3.53s/command