Python External Libraries

Python External Libraries
Table of Contents

This post is part of an ongoing series - see all the posts below.

Python for Network Engineers

Way back in part 1, I showed you a preview of a Netmiko script that connects to a Cisco device, runs a show interface status, and prints the output. At the time, I said "do not worry about understanding this, by the end of the series, it will all make sense." That time has come. In this chapter, we will finally understand every line of that script.

Before we can do that though, we need to cover a few important things. Back on part 7, we looked at Python's standard library, the modules that come bundled with Python out of the box, like random, datetime, and json. Those are useful, but they are only a small part of what Python can do. The real power of Python comes from external libraries, code written by other people that you can install and use in your own scripts.

Netmiko is one of these external libraries. It does not come with Python, you have to install it separately. Once installed, you can use it just like any other module, with a simple import statement.

In this chapter, we will look at how external libraries work, install and use PIP (Python's package manager), set up a virtual environment (a properly isolated workspace for your project), install Netmiko, and finally write a real script that connects to a network device. By the end, you will have your first working piece of network automation.

What is an External Library

An external library (also called a package or a third-party library) is a collection of Python code that someone else has written and published, so that you and I can install and use it in our own scripts. There are hundreds of thousands of them, covering everything from web development to data science to network automation.

For network engineers, some of the most useful external libraries include:

  • Netmiko - connects to network devices over SSH and sends commands
  • NAPALM - a multi-vendor network automation library
  • Requests - makes HTTP requests, essential for working with REST APIs
  • Jinja2 - a templating engine, used to generate device configurations
  • Nornir - a Python-based automation framework designed for network engineers

All of these need to be installed separately, and they all live on a website called PyPI (Python Package Index), which is like an app store for Python libraries. You do not have to visit the website to install them though; that is what PIP is for.

PIP, Python's Package Manager

PIP is the tool that installs external libraries onto your computer. It comes bundled with modern versions of Python, so you probably already have it installed. To check, run the following command in your terminal.

❯ pip --version
pip 23.0.1 from /Users/suresh/.pyenv/versions/3.10.12/lib/python3.10/site-packages/pip (python 3.10)

Just like with python and python3, the difference between pip and pip3 is that pip may refer to the version linked to Python 2 on some systems, while pip3 is linked to Python 3. On most modern systems both work the same, but if you run into issues, use pip3 to be safe.

If PIP is not installed, you may need to install it manually. On Ubuntu, for example, you can install it with the following command.

sudo apt install python3-pip

There are guides online for other operating systems if needed. Just make sure you have PIP installed before moving on.

Virtual Environments (venv)

Before we install Netmiko, we also need to talk about virtual environments. This is one of those topics that can feel unnecessary when you are just starting out, but trust me, once you understand it, you will never install a Python library without one again.

By default, when you install a library with PIP, it goes into your global Python installation. Every project on your system shares the same set of libraries and the same versions. This is fine for a while, but it causes problems as soon as you have more than one project. What if project A needs version 1.0 of a library, and project B needs version 2.0? What if you want to try out a new library without polluting your global setup? What if you want to delete a project cleanly without leaving all its libraries behind?

A virtual environment solves all of this. It is basically a private, isolated workspace for one project. Each virtual environment has its own copy of Python and its own set of installed libraries. What you install inside one virtual environment does not affect any other project on your system.

Creating a Virtual Environment

Python comes with a built-in module called venv that creates virtual environments. First, open your terminal and navigate to the project folder where you want to work.

mkdir netmiko_lab
cd netmiko_lab

Then create a virtual environment inside it with the following command.

python3 -m venv venv

This tells Python to use the venv module to create a virtual environment in a folder called venv. You can name this folder anything you want, but venv is the common convention. Inside this folder, Python stores its own copy of the interpreter and a place for your project's libraries.

On some Linux systems, if you get an error saying venv is not installed, you can install it with the following command.

sudo apt install python3.10-venv

Adjust the version number to match your Python version.

Activating the Virtual Environment

Once created, you need to activate the virtual environment before using it. Activation tells your terminal, “from now, use the Python and PIP that live inside this virtual environment, not the global ones."

On macOS, Linux, or WSL, run the following.

source venv/bin/activate

On Windows Command Prompt, run the following instead.

venv\Scripts\activate

Once activated, your terminal prompt will usually change to show (venv) at the start, depending on your terminal theme.

(venv) ❯

That is your visual confirmation that the virtual environment is active. Anything you install with PIP now will go inside this environment, not into your global Python setup.

When you are done working on the project, you can deactivate the virtual environment with the following command.

deactivate

Your prompt will go back to normal, and you will be using your global Python again.

Why Bother

If this feels like a lot of setup for something simple, I understand. But the moment you have two projects with conflicting library versions, or the moment you break your global Python installation trying to install something, you will be very glad you got into the habit of using virtual environments. It only takes a few seconds to set up, and it saves you a huge amount of pain later.

The rule of thumb is one virtual environment per project. Every time you start a new Python project, create a fresh virtual environment inside it and install everything there.

Installing Netmiko

Now that our virtual environment is active, we can install Netmiko. This is the same as any other library, use PIP.

pip install netmiko
or
pip3 install netmiko

PIP will download Netmiko from PyPI, along with any other libraries Netmiko itself depends on (like Paramiko), and install them into your virtual environment. This might take a few seconds.

You can verify the installation with the following command.

pip list
pip list
Package        Version
-------------- -------
bcrypt         5.0.0
cffi           2.1.0
cryptography   49.0.0
invoke         3.0.3
markdown-it-py 4.2.0
mdurl          0.1.2
netmiko        4.7.0
ntc_templates  9.2.0
paramiko       4.0.0
pip            26.0.1
pycparser      3.0
Pygments       2.20.0
PyNaCl         1.6.2
pyserial       3.5
PyYAML         6.0.3
rich           15.0.0
ruamel.yaml    0.19.1
scp            0.15.0
textfsm        2.1.0

This shows you every library installed in your current environment. You should see Netmiko in the list, along with a version number.

You might be looking at that list and wondering why there are so many libraries when you only installed Netmiko. The answer is dependencies. Most Python libraries rely on other libraries to do their job, and those in turn may rely on even more libraries. When you install Netmiko, PIP automatically installs everything Netmiko needs to work, and everything those libraries need, and so on down the chain.

For example, Netmiko uses Paramiko to manage the actual SSH connections, Paramiko uses cryptography and PyNaCl for encryption, cryptography uses cffi and pycparser to talk to lower-level C libraries, and so on. You did not have to think about any of this, PIP handled it all for you.

This is one of the reasons virtual environments are so useful. All of these dependencies stay contained inside the virtual environment, so they do not pollute your global Python setup or clash with other projects that might need different versions of the same libraries.

Because we installed it inside a virtual environment, it is only available while the environment is active. Deactivate the environment and run pip list again, and you will see a different (much smaller) list. This is the isolation we talked about earlier.

Revisiting the Import statement

We saw the import statement back in Chapter 7 when we used the random module. Importing an external library works exactly the same way. Python does not care whether a module came bundled with it or was installed with PIP, once it is available to your environment, you can import it with the same syntax.

import netmiko

Or, if you only need a specific piece of the library, you can use from ... import ....

from netmiko import ConnectHandler

In the Netmiko script we are about to break down, we use the second style, because we only need one specific class from Netmiko, ConnectHandler.

Understanding the Netmiko Script

Now for the moment we have been building up to. Here is the same script from Chapter 1.

from netmiko import ConnectHandler

cisco_01 = {
    "device_type": "cisco_ios",
    "host": "192.168.202.101",
    "username": "admin",
    "password": "admin"
}

connection = ConnectHandler(**cisco_01)

output = connection.send_command("show ip interface brief")
print(output)

connection.disconnect()

Output

python3 main.py
 
Interface              IP-Address      OK? Method Status                Protocol
Ethernet0/0            192.168.202.101 YES TFTP   up                    up      
Ethernet0/1            172.16.1.0      YES manual up                    up      
Ethernet0/2            unassigned      YES unset  administratively down down    
Ethernet0/3            unassigned      YES unset  administratively down down    
Loopback0              10.0.0.1        YES manual up                    up
Never store credentials in plain text in a production script. There are much better ways to handle this, environment variables, secret managers, prompting the user at runtime, or loading them from a separate file that is not shared. We will look at how to do this properly in the next chapter, along with more of what Netmiko can do.

Let's break it down line by line.

The Import

from netmiko import ConnectHandler

We are importing the ConnectHandler class from the Netmiko library. Do not worry about what a class is for now, just think of it as a special kind of function that Netmiko gives us to connect to devices. This is the same import syntax we used with the random module in Chapter 7.

The Device Dictionary

cisco_01 = {
    "device_type": "cisco_ios",
    "host": "192.168.202.101",
    "username": "admin",
    "password": "admin"
}

This is just a dictionary, which we covered in detail back in Chapter 5. It holds all the details Netmiko needs to connect to our device, the device type, the IP address, the username, and the password. Netmiko supports many different device types (cisco_ios, arista_eos, juniper_junos, nokia_srl, and many more), and setting the right device_type is important because Netmiko uses it to know how to talk to that specific device.

Creating the Connection

connection = ConnectHandler(**cisco_01)

This is the line that actually connects to the device. ConnectHandler is the function (technically a class) we imported from Netmiko. It takes a bunch of keyword arguments like device_type, host, username, and password, and returns a connection object that we can use to send commands.

The **cisco_01 bit is called dictionary unpacking. It tells Python, "take every key in this dictionary and pass it as a keyword argument, with its value." So this line is equivalent to writing the following.

connection = ConnectHandler(
    device_type="cisco_ios",
    host="192.168.202.101",
    username="admin",
    password="admin"
)

Both work exactly the same. Using a dictionary is cleaner though, especially when you have multiple devices, because you can store their details separately and unpack them as needed.

The result is stored in a variable called connection, which represents the active SSH session to our device.

Sending a Command

output = connection.send_command("show ip interface brief")
print(output)

send_command is a method on the connection object. Remember from Chapter 3, a method is something you call on a value using dot syntax. This method takes a command as a string, sends it to the device, waits for the response, and returns the output as a string. We store that string in output and print it.

Behind the scenes, Netmiko is doing a lot of work here, waiting for the command prompt, sending the command, reading the response, stripping out any weird terminal characters, and giving us clean output. Without Netmiko, we would have to write all of that ourselves.

Disconnecting

connection.disconnect()

Finally, we close the SSH session. This is important, if you forget to disconnect, you might leave orphaned sessions on the device, and eventually run out of allowed connections. Always disconnect when you are done.

I hope the entire script makes sense to you. Every single line uses concepts we have already covered in this series, imports (Chapter 7), dictionaries (Chapter 5), variables (Chapter 2), method calls (Chapter 3), and functions (Chapter 6). The only thing that was new was the Netmiko library itself, and even that is just a collection of functions and classes that someone else (Thank you Kirk Byers) wrote for us to use.

Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Packetswitch.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.