Exceptional update
Programming has become an essential skill to automate and manage network infrastructure effectively. Python, with its simplicity and versatility, is the go-to programming language of choice in the networking domain. In a previous blog post, I attempted to explain a Python script that I had learned how to build earlier in the same day. That code was set up to handle exceptions, but in my excitement of what the code could do, I stumbled and fumbled a bit through explaining the code I'd just written. That basically highlighted to me the fact that more training was needed. I tried to fill in those learning gaps as best I could with some supplemental reading. Today, I'm going to revisit the concept of Python exceptions and hopefully help you understand how they can be applied in network engineering.
What are Python Exceptions?
Exceptions are events that occur during the execution of a program, disrupting the normal flow of instructions. Basically, if your code encounters an input that was not expected, the default behavior is to kick out an error message, and the code stops running at the point of the error, or more correctly, exception. What can be done? In Python, exceptions handle errors and unexpected behavior, be they from erroneous human input or a response from a network device that was not programmed for. When an exception arises, Python can create an exception object that can be used later in the code. It's a pretty neat and very flexible solution.
Exceptions come into play when using the try command (not sure if we want to call it a command as we would in Linux, but its the best way I have to identify how it works at this point) much the same way an else is used in concert with and if statement.
Here's an outline of the syntax:
Why it Matters
In network engineering, we often deal with various scenarios where exceptions can occur. For example, connecting to network devices or performing other network operations can generate exceptions. Using the try-except block, we can gracefully handle these exceptions and ensure our programs continue to run smoothly.
–OK– so I had to take a break from writing this post and am only now getting back to it. I hope it doesn't seem too disjointed. Here goes with the rest of it.
Where you will see exceptions
Let's take a look at some common exceptions in network engineering:
- ConnectionError: Happens when a connection to a network device fails, such as when using SSH or Telnet protocols.
- TimeoutError: Raised when a network operation exceeds a timeout limit, indicating a delay or unresponsiveness–does what it says on the tin.
- ValueError: Occurs when an inappropriate value is passed to a network-related function, such as an invalid IP address or port number. You will also see this particular error is the value returned is the wrong type of input, for example, if a user is prompted to enter an integer but types a string instead, there will be a ValueError.
- FileNotFoundError: Results from attempting to access a network configuration file that cannot be found, similar to a 404 error when trying to access a webpage that doesn't exist.
What to do
To handle exceptions effectively, it is important to understand the specific exception types that may arise in network engineering scenarios (see the list above). By anticipating potential exceptions and incorporating appropriate exception handling, we can improve the reliability and robustness of our network automation scripts.
A little bit more
The try-except block can be enhanced with an else block and a finally block:
- The else block works the same way it does within the context of an if statement, but it is executed only if no exceptions occur within the try block. It is used to perform actions that should only occur when no exceptions are raised. For instance, we can use this block to display success messages or trigger subsequent network operations.
- The finally block is always executed, regardless of whether an exception occurred or not. It is typically used to perform cleanup operations, such as closing network connections or releasing resources. You don't want the script to run indefinitely, do you? This ensures that our network infrastructure remains in a consistent state even if exceptions were encountered.
Here is an example that help me to understand handling exceptions. Feel free to run it in your own environment. If you do so and enter a number when prompted, the code will divide and print the answer. Should you for some reason enter you name or anything that is not a number (!= number), you will activate the exception handling. Give it a try.
Coming back to the example I struggled with
As you see, the code initializes a connection withe host at cisco.com on port 22 using the username and password provided as defined in the Netmiko Python library to be a cisco_ios device. The first thing that happens in the try block is an attempt to establish a connection using the ConnectHandler that is stored as the variable "c." the ConnectHandler sends in the Cisco "enable" command and on successful response from the router, the command "show ip inter bri" (shorthand for "show ip interface brief") is issued and then a disconnect is sent to close the connection. If the above fails for whatever reason, the exception is held as the variable "ex" and then printed to the screen, otherwise the router's response is displayed and you will have effectively issued the desired cli command through the use of Netmiko and Python.
Ultimately, by utilizing the try-except block, network engineers can handle exceptions that may come up while managing network devices. Understanding common exception types and incorporating appropriate exception handling allows us to build robust and reliable network automation scripts. Keep in mind, effective exception handling is key to ensuring network stability and efficiency–whether you are using Python and Netmiko or handling the exceptions per hand on the cli.
HTH