Modules

A module in python is a file that contains a subset of code. It is a way to organize your code by grouping functions and objects in a meaningful way. If you are writing an application that configures router interfaces via the NXOS-API ReST interface, you could organize that code into modules such that it is easy to reference back. For example a module could contain all the code that manages creating the configuration for Cisco IOS while another module might containg the configuration for NX-OS.

Modules also provide a mechanism to create granularity in how you reference a function, class or object. This will become more and more evident when working with large libraries such as the Cobra SDK for ACI. In the following two examples we have a function that we have called ospf_area. At a high level this function makes sense to exist or provide the functionality for different boxes (say IOS or NX-OS ). By utilizing separate modules you could call the specific function even though both are named the same by referencing that function as a relationship to it's module.


file:ios.py

def ospf_area( oarea ):
    [do something to return a config]

def ospf_routerID( ip ):
    [do something to return a config]
    

file: nxos.py

def ospf_area( oarea):
    [do something to return a config]

def ospf_routerID( ip ):
    [do something to return a config]

Now each function can be independently referenced based on it's module reference.


ios.ospf_area("0")

nxos.ospf_area("0")

Importing Modules

Modules can also be imported into your file providing a local reference. There are three different methods of importing objects from modules.

Utilizing the same example as before we can import the function ospf_area that we require in our code execution. Since you would know the execution required ( for NXOS or IOS ) you can select the proper function from the module file in a way to remove the reference requirement.


from ios import ospf_area

ospf_area("0")

from nxos import ospf_area

ospf_area("0")

While this is possible, sometimes this can lead to harder to read code. Utilizing the module reference provides a structural view of the code written to understand a reference quicker. Using the example above it would require knowing what was imported before understanding what code to work with. For this reason in some cases it is better to utilize the full module reference.

A note on asterisk imports

An important note on doing the command from module import * is that any object that starts with underscore is not automatically imported. These are known as private names ( not to be confused with private objects in classes ). This is used to hide functions that are of local significance to the module file. This only applies to *. You can still import the specific object by specifying the import directly ( as an exmaple: from module import _g

A good example of how modules can be accessed can be observed in the various ways that you can reference the Cobra SDK to access the ACI ReST API. In the following example there are two import statements. import cobra.mit.access and the session module. Then the function is accessed via the module path information.


import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
import cobra.mit.access
import cobra.mit.session

def connect_to_apic():
    apicurl = 'http://%s' % "10.x.x.x"
    modir = cobra.mit.access.MoDirectory(cobra.mit.session.LoginSession(apicurl, "admin", "cisco.123"))
    modir.login()
    return modir

mo_dir = connect_to_apic()
    

Now take a look at how the Cobra SDK is accessed when you specify the module exactly that you wish to import.


import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
from cobra.mit.access import MoDirectory
from cobra.mit.session import LoginSession

def connect_to_apic():
    apicurl = 'http://%s' % "10.x.x.x"
    modir = MoDirectory(LoginSession(apicurl, "admin", "cisco.123"))
    modir.login()
    return modir

mo_dir = connect_to_apic()