We have seen how to achieve parallel task execution in python using multi-threading as in the below-linked post. Let’s see how we can leverage Python Scrapli AsyncIO to achieve similar results.
Part1 of scrapli can be found here
What is AsyncIO?
asyncio is a library to write concurrent code using the async/await syntax. asyncio is used as a foundation for multiple Python asynchronous frameworks that provide high-performance network and web-servers, database connection libraries, distributed task queues, etc. asyncio is often a perfect fit for IO-bound and high-level structured network code.
Thanks to the great contribution by Carl Montanari’s Scrapli library, the heavy lifting to use AsyncIO has already been baked inside the library.
https://carlmontanari.github.io/scrapli/
Let’s see how a basic Python Scrapli AsyncIO Usage looks like
import asyncio
from scrapli.driver.core import AsyncIOSXEDriver
IOS_XE = {
"host": 'sandbox-iosxe-latest-1.cisco.com',
"auth_username": "developer",
"auth_password": "C1sco12345",
"auth_strict_key": False,
"transport": "asyncssh",
}
async def main():
async with AsyncIOSXEDriver(**IOS_XE) as conn:
results = await conn.send_command("show version")
print(results.result)
if __name__ == "__main__":
asyncio.run(main())
# asyncio.get_event_loop().run_until_complete(main()) # python <3.7
Explanation:-
- Import asyncio
- import AsyncIOSXEDriver or the suitable driver based on the device type but make sure to get the async version.
- Define the device dictionary
- Create a function to perform the routine you want on the device.
- asyncio.run(main()) to execute the task.
The true benefit of asyncIO is realized when you want to fetch multiple command outputs from multiple devices at once.
"""examples.async_usage.async_multiple_connections"""
import asyncio
from scrapli.driver.core import AsyncIOSXEDriver, AsyncIOSXRDriver, AsyncNXOSDriver
csr1000v1 = {
'host': 'sandbox-iosxe-latest-1.cisco.com',
'auth_username': 'developer',
'auth_password': 'C1sco12345',
"auth_strict_key": False,
"transport": "asyncssh",
"driver": AsyncIOSXEDriver
}
iosxrv9000 = {
'host': 'sandbox-iosxr-1.cisco.com',
'auth_username': 'admin',
'auth_password': 'C1sco12345',
"auth_strict_key": False,
"transport": "asyncssh",
"driver": AsyncIOSXRDriver
}
DEVICES = [csr1000v1, iosxrv9000]
async def fetch_data(device):
driver = device.pop("driver")
async with driver(**device) as conn:
responses = await conn.send_commands(["show ip int brief", "show version"])
return responses
async def main():
coroutines = [fetch_data(device) for device in DEVICES]
results = await asyncio.gather(*coroutines)
for result in results:
print(result.result)
if __name__ == "__main__":
asyncio.run(main())
# asyncio.get_event_loop().run_until_complete(main())
Read more about Multithreading vs Multiprocessing vs Asynchronous
the output is append with the command, how can we clean the output??
Hi Oscar,
Your answer hides in this function.
async def fetch_data(device):
driver = device.pop("driver")
async with driver(**device) as conn:
responses = await conn.send_commands(["show ip int brief", "show version"])
return responses
This is the collector function. You can play around with this function to take the desired output the way you want.
async def fetch_data(device):
driver = device.pop("driver")
async with driver(**device) as conn:
responses = await conn.send_commands(["show ip int brief", "show version"])
for response in responses:
print(dir(response)) ---> use dir() to explore the output and possible options.
print("-------------------------------")
print(response.channel_input)
print("-------------------------------")
print(response.response)
print(response.result)
return responses