In this post, we will cover some best practices that will help you write good-quality Python code. By this, I mean code that:

  • It is easy to read
  • Clear in its intent
  • Aligns to the Python naming standards

Let's dive in …

Naming - Casing and Grammar

When writing Python code, following naming conventions for variables, functions, and classes is good practice. Here are the general rules for naming conventions in Python:

Casing Grammar Example
Classes CamelCase Noun Router
Variables (and attributes) lowercase with underscores Noun vlan_name
Functions (and methods) lowercase with underscores Verb get_vlan()

Here are the examples shown a little differently:

# Class
# - Noun
# - CamelCase
class Router(object):
    ...

# Variables
# - Noun
# - lowercase /w underscores
vlan_name = "VLAN_100"

# Methods/functions
# - Verb
# - lowercase /w underscores
def get_vlan_id():
    ....

Naming - Type and Length

When naming within Python, consider the type and length of what you are naming. The name should represent its scope and have some reference to its value. For example:

vlan_ids = [100, 200, 300]

# what does x relate to?
for x in vlan_ids:
    print(x)

# name length is too long for its scope
for the_vlan_id_in_loop in vlan_ids:
    print(the_vlan_id_in_loop)

A much better example of naming is:

# short name for scope (as it's only used within the loop),
# and v relates to vlan_id
for v in vlan_ids:
    print(v)

Furthermore, if we need to ignore a variable, we can ignore the value and declare that it is not required by assigning it against _ like so:

vlan_100, _, vlan_300 =  [100, 200, 300]

Will this speed up your scripts or reduce the memory footprint? Not really, but it will clearly show your code's intent, making it easier to read and understand.

Functions

Functions should be small and only do one thing. For example. If we look at the following:

from netmiko import ConnectHandler

device = {
    'device_type': 'cisco_ios',
    'ip': '10.1.1.1',
    'username': 'admin',
    'password': 'admin',
}

def is_vlan_present(vlan_id):
    with ConnectHandler(**device) as conn:
        vlans = conn.send_command('show vlan', use_textfsm=True)

    for vlan in vlans:
        if vlan['vlan_id'] == vlan_id:
            return True
    return False

is_vlan_present(100)
# Output:
# True

We can see that is_vlan_present is doing 2 things. Its fetching the data and then checks the data. A much better approach is to create 2 functions like so:

from netmiko import ConnectHandler

device = {
    'device_type': 'cisco_ios',
    'ip': '10.1.1.1',
    'username': 'admin',
    'password': 'admin',
}

def get_vlans():
    with ConnectHandler(**device) as conn:
        output = conn.send_command('show vlan', use_textfsm=True)

    return output

def is_vlan_present(vlan_id):
    vlans = get_vlans()
    for vlan in vlans:
        if vlan['vlan_id'] == vlan_id:
            return True
    return False

is_vlan_present(100)
# Output:
# True

Note: This is just an example to show the point; in the real world, this would be written much more effectively (i.e. not connecting to the device for each VLAN check).

Styling

When it comes to styling, i.e. indents, spacing etc., there are a few tools that you can use to automate the process of updating the styling of your Python scripts. The defacto tool that is currently used it, Black. Which is a general-purpose formatter.

Here's a quick example:

$ pip install black
$ cat my_script.py (BEFORE)
vlans = [
{"vlan_name": "SALES", "vlan_id": 100},
{"vlan_name": "HR", "vlan_id": 101},{"vlan_name": "FINANCE", "vlan_id": 102}
]

def is_vlan_present( vlan_id ):
    for vlan in vlans:
        if vlan_id in vlan.values():
            return True
    return False
$ black my_script.py 
All done! ✨ 🍰 ✨
1 file reformatted.
$ cat my_script.py (AFTER)
vlans = [
    {"vlan_name": "SALES", "vlan_id": 100},
    {"vlan_name": "HR", "vlan_id": 101},
    {"vlan_name": "FINANCE", "vlan_id": 102},
]

def is_vlan_present(vlan_id):
    for vlan in vlans:
        if vlan_id in vlan.values():
            return True
    return False

That's it for this post on Python coding best practices. I hope you found it helpful and happy coding!

Ready to Master Network Automation? Start Your Journey Today!
Our membership provides:
  • Full deep-dive course library (inc. Batfish, pyATS, Netmiko)
  • Code repositories inc. full course code, scripts and examples
  • 24x7 multi-vendor labs (Arista, Cisco, Juniper)
  • Private online community
  • Live monthly tech sessions
  • Access to tech session library

Join Now ➜