pyATS Async
pyATS Async is a sub-component of the pyATS ecosystem, a Python-based framework by Cisco specializing in data-driven and reusable network testing and automation. It wraps Python's multiprocessing module to enable asynchronous (parallel) execution of arbitrary functions. The library, currently at version 26.3, is actively maintained with a frequent release cadence, often monthly or bi-monthly.
Common errors
-
ImportError: cannot import name 'pcall' from 'pyats.async'
cause Attempting to import `pcall` from the old `pyats.async` module path, which was renamed to `pyats.async_` in pyATS v19.0 to avoid conflicts with Python 3.7's `async` keyword.fixChange the import statement to `from pyats.async_ import pcall`. -
TypeError: 'NoneType' object is not iterable (when using with pyATS topology/devices)
cause This error often occurs when attempting to call a method like `.parse()` or iterate over a device object that failed to connect within a broader pyATS testbed setup. In parallel execution scenarios, if some device connections fail, subsequent operations on those 'None' or unconnected device objects will raise this error if not explicitly handled.fixImplement robust error handling and checks for device connectivity (e.g., `if device.connected:` or `if device:` before attempting operations) when working with `pyats.topology` devices, especially in asynchronous contexts.
Warnings
- breaking The `pyats.async` module was renamed to `pyats.async_` starting with pyATS v19.0 (March 2019) to resolve conflicts with the `async` keyword introduced in Python 3.7. Code using the old import path will break on Python 3.7 and newer.
- gotcha pyATS and its sub-components, including `pyats.async`, do not officially support Windows operating systems. It is designed for and tested on Linux and Mac systems. Running on Windows may lead to unexpected behavior, installation failures, or runtime errors.
- gotcha `pyats.async` leverages Python's multiprocessing for true parallelism, which is ideal for CPU-bound tasks. It should not be confused with `asyncio`, which is designed for I/O-bound (non-blocking) tasks and uses a single-threaded event loop. Using `pyats.async` for I/O-bound operations might not provide the expected performance benefits, and combining it incorrectly with `asyncio` can introduce complexity.
Install
-
pip install pyats.async
Imports
- pcall
from pyats.async import pcall
from pyats.async_ import pcall
Quickstart
import time
from pyats.async_ import pcall
def my_cpu_bound_task(item):
"""A sample CPU-bound task that simulates work."""
# print(f"Starting task for item {item}...") # Uncomment to see individual task starts
time.sleep(1) # Simulate some CPU-intensive work
result = item * item
# print(f"Finished task for item {item}, result: {result}") # Uncomment to see individual task finishes
return result
if __name__ == "__main__":
items_to_process = [1, 2, 3, 4, 5]
print("\n--- Running tasks in parallel with pcall ---")
# pcall executes the function in parallel processes and returns results in order.
parallel_results = pcall(my_cpu_bound_task, *items_to_process)
print(f"All parallel tasks completed. Results: {parallel_results}")
print("\n--- Running tasks synchronously for comparison ---")
sync_results = [my_cpu_bound_task(item) for item in items_to_process]
print(f"All synchronous tasks completed. Results: {sync_results}")