5
\$\begingroup\$

I am a network engineer and started playing with Python as a way to supplement some downtime in the job. We have no automation at the company so I was playing around with making a GUI to run simple commands to our equipment and give the output in a separate window. The main window (root) stays active the whole time so that you can change the connected device, credentials, IP, etc which makes it "faster" to scout issues.

I never took any Python classes and each part of the code was picked up on the fly from different sources, but I picked up enough to figure out what I needed.

I don't really have a problem with the code other than scrollbars not working, but I know why so not a problem at the moment.

Since I have nobody on my team that can tell me if this code is good or bad I was curious to see if someone could just look at the code and tell me what they think.

#Imported packages. You may need to run "pip install <package>" where <package> is the package listed below. If you are
#unsure how to install Python packages then try looking at instructions here:
# https://packaging.python.org/tutorials/installing-packages/#
from netmiko import (
    ConnectHandler,
    NetmikoTimeoutException,
    NetmikoAuthenticationException,
)
from getpass import getpass
from tkinter import *

#Sets up the main window#
root = Tk()
root.title("Cisco Troubleshooter")
root.configure(background="black")
root.iconbitmap('cisco.ico')

def on_device_click(event):
    """function that gets called whenever entry is clicked"""
    if device.get() == "Enter the IP/Hostname you want to connect to":
        device.delete(0, "end")  # delete all the text in the entry
        device.insert(0, '')  # Insert blank for user input
        device.config(fg='black')


#Displays red text if the box is clicked on, not filled out, then exited#
def on_device_focusout(event):
    if device.get() == '':
        device.insert(0, "Enter the IP/Hostname you want to connect to")
        device.config(fg="red")


def on_UN_click(event):
    if UN.get() == "Enter your username":
        UN.delete(0, "end")  # delete all the text in the entry
        UN.insert(0, '')  # Insert blank for user input
        UN.config(fg='black')


#Displays red text if the box is clicked on, not filled out, then exited#
def on_UN_focusout(event):
    if UN.get() == '':
        UN.insert(0, "Enter your username")
        UN.config(fg="red")


def on_PW_click(event):
    if PW.get() == "*":
        PW.delete(0, "end")  # delete all the text in the entry
        PW.insert(0, '')  # Insert blank for user input
        PW.config(fg='black')

    elif PW.get() == "Enter your password":
        PW.delete(0, "end")  # delete all the text in the entry
        PW.insert(0, '')  # Insert blank for user input
        PW.config(fg='black')


#Displays red text if the box is clicked on, not filled out, then exited#
def on_PW_focusout(event):
    if PW.get() == '':
        PW.insert(0, "Enter your password")
        PW.config(fg="red")

def on_IP_click(event):
    if IP.get() == "Enter IP for commands":
        IP.delete(0, "end")  # delete all the text in the entry
        IP.insert(0, '')  # Insert blank for user input
        IP.config(fg='black')


#Displays red text if the box is clicked on, not filled out, then exited#
def on_IP_focusout(event):
    if IP.get() == '':
        IP.insert(0, "Enter IP for commands")
        IP.config(fg="green")

def on_INT_click(event):
    if INT.get() == "Enter Int/MAC/VLAN for commands":
        INT.delete(0, "end")  # delete all the text in the entry
        INT.insert(0, '')  # Insert blank for user input
        INT.config(fg='black')


#Displays red text if the box is clicked on, not filled out, then exited#
def on_INT_focusout(event):
    if INT.get() == '':
        INT.insert(0, "Enter Int/MAC/VLAN for commands")
        INT.config(fg="green")


#Sets up the "show active calls" button payload#
def active_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host": device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        active = (ssh.send_command("sh call active voice comp"))

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (active)

        # Prints the output in the Python window for QA purposes#
        print(active)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN,  bg="black", fg="light green", justify=LEFT)
        label.grid(row=0, column=0, sticky=NS)

    # Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky=NSEW)


#Sets up the "show bgp summary" button payload#
def bgpsumm_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host": device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        bgpsumm = (ssh.send_command("sh bgp summ | beg Neigh"))

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (bgpsumm)

        # Prints the output in the Python window for QA purposes#
        print(bgpsumm)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN,  bg="black", fg="light green", justify=LEFT)
        label.grid(row=0, column=0, sticky="nsew")

    #Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")


#Sets up the "show cdp neighbors" button payload#
def  cdp_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host": device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button. Pulls any entries from the interface entry box#
        if INT.get() == "Enter interface for commands":
            cdp = (ssh.send_command("sh cdp neigh "))

        else:
            cd= ssh.send_command("sh cdp neigh " + INT.get())

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (cdp)

        # Prints the output in the Python window for QA purposes#
        print(cdp)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN,  bg="black", fg="#08bc08", justify=LEFT)
        label.grid(row=0, column=0)

    # Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")


#Sets up the "show error-disabled" button payload#
def errdisable_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host": device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        errdisabled = (ssh.send_command("sh int status | i err"))

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (errdisabled)

        # Prints the output in the Python window for QA purposes#
        print(errdisabled)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN,  bg="black", fg="light green", justify=LEFT)
        label.grid(row=0, column=0, sticky=NS)

    # Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky=NSEW)


#Sets up the "show interfaces" button payload#
def showint_click():

    try:
        #Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host":device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        #Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        #Commands section for this button#
        up = (ssh.send_command("sh ip int bri | i up"))
        down = (ssh.send_command("sh ip int bri | i down"))

        #Binds the commands being run into a variable so that they can be printed neatly#
        results= ("Up Interfaces\n\n" + up + "\n\nDown Interfaces\n\n" + down + "\n")

        #Prints the output in the Python window for QA purposes#
        print("Up Interfaces\n\n" + up + "\n\nDown Interfaces\n\n" + down + "\n")

        #Disconnects from the SSH session#
        ssh.disconnect()

        #Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        #Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN, bg="black", fg="light green", justify=LEFT)
        label.grid(row=0, column=0, sticky=NS)

    #Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN)
        label.grid(row=0, column=0, sticky=NSEW)


def iparp_click():

    try:
        #Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host":device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        #Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        #Commands section for this button#
        if IP.get() == "Enter IP for commands":
            iparp = (ssh.send_command("sh ip arp "))

        else:
            iparp = (ssh.send_command("sh ip arp " + IP.get()))

        #Binds the commands being run into a variable so that they can be printed neatly#
        results= (iparp)

        #Prints the output in the Python window for QA purposes#
        print(iparp)

        #Disconnects from the SSH session#
        ssh.disconnect()

        #Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        #Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN, bg="black", fg="light green", justify=LEFT)
        label.grid(row=0, column=0, sticky=NS)

    #Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN)
        label.grid(row=0, column=0, sticky=NSEW)


#Sets up the "show isdn status" button payload#
def isdn_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host":device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        isdn = (ssh.send_command("sh isdn status"))

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (isdn)

        # Prints the output in the Python window for QA purposes#
        print(isdn)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN,  bg="black", fg="light green", justify=LEFT)
        label.grid(row=0, column=0, sticky=NS)

    #Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")


#Sets up the "show mac address" button payload#
def mac_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host": device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        if INT.get() == "Enter Int/MAC/VLAN for commands":
            mac = (ssh.send_command("show mac address-table"))

        else:
            mac = ssh.send_command("show mac address-table address " + INT.get())

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (mac)

        # Prints the output in the Python window for QA purposes#
        print(results)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN, bg="black", fg="#08bc08", justify=LEFT)
        label.grid(row=0, column=0)

    # Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")


#Sets up the "show temperature" button payload#
def temp_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host": device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        temp = (ssh.send_command("sh envi temp"))

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (temp)

        # Prints the output in the Python window for QA purposes#
        print(temp)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="ns")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN,  bg="black", fg="#08bc08", justify=LEFT)
        label.grid(row=0, column=0)

    # Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")


#Sets up the "show uptime" button payload#
def uptime_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host": device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        uptime = (ssh.send_command("sh ver | i uptime"))

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (uptime)

        # Prints the output in the Python window for QA purposes#
        print(uptime)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="ns")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN,  bg="black", fg="#08bc08", justify=LEFT)
        label.grid(row=0, column=0)

    # Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")


#Sets up the "show vlan" button payload#
def vlan_click():
    try:
        # Sets up the SSH payload#
        cisco_payload = {
            "device_type": "cisco_ios",
            "host": device.get(),
            "username": UN.get(),
            "password": PW.get(),
            "port": 22,
        }

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        vlan = (ssh.send_command("sh vlan"))

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (vlan)

        # Prints the output in the Python window for QA purposes#
        print(vlan)

        # Disconnects from the SSH session#
        ssh.disconnect()

        # Sets up the new window once the button is clicked#
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        # Creates the scrollbar#
        scroll = Scrollbar(output, orient=VERTICAL)
        scroll.grid(row=0, column=1, sticky="nsew")

        # Creates the section in the new window where the text will be printed then prints it#
        label = Label(output, text=results, relief=SUNKEN, bg="black", fg="#08bc08", justify=LEFT)
        label.grid(row=0, column=0)

    # Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")


#Sets up the command to exit the program on button click#
def quit_click():
    root.destroy()

#IP/Hostname entry field#
device = Entry(root, width=60, borderwidth=20, fg="black")
device.insert(0, "Enter the IP/Hostname you want to connect to")
device.bind("<FocusIn>", on_device_click)
device.bind("<FocusOut>", on_device_focusout)
device.grid(row=0, column=0, columnspan=2, sticky="nsew")

#Username entry field#
UN = Entry(root, width=60, borderwidth=20, fg="black")
UN.insert(0, "Enter your username")
UN.bind("<FocusIn>", on_UN_click)
UN.bind("<FocusOut>", on_UN_focusout)
UN.config(fg="gray")
UN.grid(row=1, column=0, columnspan=2, sticky="nsew")

#Password entry field#
PW = Entry(root, show="*", width=60, borderwidth=20, fg="black")
PW.insert(0, "*")
PW.bind("<FocusIn>", on_PW_click)
PW.bind("<FocusOut>", on_PW_focusout)
PW.config(fg="gray")
PW.grid(row=2, column=0, columnspan=2, sticky="nsew")

#IP for commands entry field#
IP = Entry(root, width=30, borderwidth=20, fg="black")
IP.insert(0, "Enter IP for commands")
IP.bind("<FocusIn>", on_IP_click)
IP.bind("<FocusOut>", on_IP_focusout)
IP.config(fg="gray")
IP.grid(row=3, column=0, sticky="nsew")

#Interface entry field#
INT = Entry(root, width=30, borderwidth=20, fg="black")
INT.insert(0, "Enter Int/MAC/VLAN for commands")
INT.bind("<FocusIn>", on_INT_click)
INT.bind("<FocusOut>", on_INT_focusout)
INT.config(fg="gray")
INT.grid(row=3, column=1, sticky="nsew")

#Creates the "show active calls" button#
active = Button(root, text="Show Active Calls", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=active_click)
active.grid(row=4, column=0, sticky="nsew")

#Creates the "show bgp summary" button#
bgpsumm = Button(root, text="Show BGP Summary", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=bgpsumm_click)
bgpsumm.grid(row=4, column=1, sticky="nsew")

#Creates the "show cdp neighbors" button#
cdp = Button(root, text="Show CDP neighbors", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=cdp_click)
cdp.grid(row=5, column=0, sticky="nsew")

#Creates the "show error-disabled" button#
errdisable = Button(root, text="Show Err-Disabled Interfaces", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=errdisable_click)
errdisable.grid(row=5, column=1, sticky="nsew")

#Creates the "show interfaces" button#
showint = Button(root, text="Show Interfaces", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=showint_click)
showint.grid(row=6, column=0, sticky="nsew")

#"show ip arp" button"
isdn = Button(root, text="Show IP ARP", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=iparp_click)
isdn.grid(row=6, column=1, sticky="nsew")

#"show isdn status" button"
isdn = Button(root, text="Show ISDN Status", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=isdn_click)
isdn.grid(row=7, column=0, sticky="nsew")

#Creates the "show mac" button#
mac = Button(root, text="Show MAC Address", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=mac_click)
mac.grid(row=7, column=1, sticky="nsew")

#Creates the "show temperature" button#
temp = Button(root, text="Show Temperature", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=temp_click)
temp.grid(row=8, column=0, sticky="nsew")

#Creates the "show uptime" button#
uptime = Button(root, text="Show Uptime", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=uptime_click)
uptime.grid(row=8, column=1, sticky="nsew")

#Creates the "show VLAN" button#
vlan = Button(root, text="Show VLAN", width=30, bg="#08bc08", pady=2, fg="black", borderwidth=10, command=vlan_click)
vlan.grid(row=9, column=0, sticky="nsew")

#Creates the "quit" button#
quit = Button(root, text="Quit", width=30, bg="red", fg="black", borderwidth=10, command=quit_click)
quit.grid(row=10, column=1, sticky="nsew")

#Row number buttons start at. Used for start of button auto re-size loop#
button_row_num = 4

#Creates button list#
button_list = [active, bgpsumm, cdp, errdisable, showint, isdn, temp, vlan, quit]

for button in button_list:
    Grid.rowconfigure(root, button_row_num, weight=1)
    Grid.columnconfigure(root, 0, weight=1)
    Grid.columnconfigure(root, 1, weight=1)
    button_row_num +=1

#Runs the app#
root.mainloop()
\$\endgroup\$
2
  • \$\begingroup\$ Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to edit and give it a different title if there is something more appropriate. I also added the beginner tag but if you feel you aren't a beginner anymore then feel free to remove it. \$\endgroup\$ Aug 31 at 20:50
  • 1
    \$\begingroup\$ Thanks for having me and making the title more relevant. I will leave the beginner flag because I don't even think I am good enough to be a beginner right now :D \$\endgroup\$
    – Girliman
    Aug 31 at 20:57
3
\$\begingroup\$

Consider replacing this:

#Imported packages. You may need to run "pip install <package>" where <package> is the package listed below. If you are
#unsure how to install Python packages then try looking at instructions here:
# https://packaging.python.org/tutorials/installing-packages/#

with an actual requirements.txt consumable by pip install -r, and spelling out what your package requirements are. You can even drop a comment in there showing how to pass the file to pip; but your comment as it stands is less than helpful because it doesn't actually say what your requirements are.

Try to remove root from the global namespace so that your code can be re-entrant. The most typical approach to this is to put it in a class. Likewise, nothing after #IP/Hostname entry field# should be left global.

Does your program support entering the password (literally) Enter your password? I suspect not. You could get really fancy and have change tracing enabled to know when someone has entered their own text, but the easier and less surprising thing to do is to remove the placeholder text from the textbox and put it in a separate label.

There's not really a point to forming the dictionary cisco_payload, since you only use it for one set of kwargs. Instead, just

ssh = ConnectHandler(
    device_type='cisco_ios',
    host=device.get(),
    username=UN.get(),
    password=PW.get(),
    port=22,
)

Also note that UN and PW should be neither capitalized nor abbreviated.

Neither of these:

    active = (ssh.send_command("sh call active voice comp"))
    results = (active)

should be parenthesized.

This block:

        # Sets the SSH payload to a variable to be used for running commands#
        ssh = ConnectHandler(**cisco_payload)

        # Commands section for this button#
        active = (ssh.send_command("sh call active voice comp"))

        # Binds the commands being run into a variable so that they can be printed neatly#
        results = (active)

        # Prints the output in the Python window for QA purposes#
        print(active)

        # Disconnects from the SSH session#
        ssh.disconnect()

should guarantee a disconnect:

# Sets the SSH payload to a variable to be used for running commands#
ssh = ConnectHandler(**cisco_payload)
        
try:
    # Commands section for this button#
    active = (ssh.send_command("sh call active voice comp"))

    # Binds the commands being run into a variable so that they can be printed neatly#
    results = (active)

    # Prints the output in the Python window for QA purposes#
    print(active)

finally:
    # Disconnects from the SSH session#
    ssh.disconnect()

You should get out of the habit of adding a # suffix to all of your comments.

There's a lot of repetition in your functions, for instance in your setup of a top-level output window like this:

    # Handles error exceptions and prints out the error#
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")

If you want to make a generic handler that does the above for any callers, make a context manager:

@contextlib.contextmanager
def handle_and_output():
    try:
        yield
    except(KeyError, KeyboardInterrupt, IndexError, NetmikoTimeoutException, NetmikoAuthenticationException) as error:
        output = Toplevel(root)
        output.title("Output Window")
        output.iconbitmap('cisco.ico')

        label = Label(output, text=error, relief=SUNKEN, bg="black", fg="light green")
        label.grid(row=0, column=0, sticky="nsew")

# ...

with handle_and_output():
    # do something risky

However, repeating the creation of a top-level window seems suspicious, and there should probably just be one instance whose reference you reuse, setting its label text.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ +1 Biggest problem with this code is that it's unnecessarily long. Repetitive code is bad because it's harder to read (longer and less meaningful), harder to change (multiple places need updated), and more error-prone (easy to update one place and forget others, for example). A common programming principle is: Don't Repeat Yourself. It's a reasonable goal to have no blocks of 2+ lines repeated or nearly-repeated, maybe even 1 line. \$\endgroup\$ Sep 1 at 8:13
  • 1
    \$\begingroup\$ Thank you both for your advice. I am going through the script and trying to make each of the changes suggested. I ain't bright enough to call functions in functions yet, but will work on making it happen. I agree the code is unnecessarily long and needs a trim. It made sense for me at the time to copy and adjust what I already had working as I was the only one modifying anything. This script has a long way to go and you both have given me the advice needed to make it better. \$\endgroup\$
    – Girliman
    Sep 1 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.