{"id":7538,"library":"pyats-async","title":"pyATS Async","description":"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.","status":"active","version":"26.3","language":"en","source_language":"en","source_url":"https://github.com/CiscoTestAutomation","tags":["pyats","async","multiprocessing","network automation","cisco"],"install":[{"cmd":"pip install pyats.async","lang":"bash","label":"Install pyats-async"}],"dependencies":[{"reason":"Required Python version","package":"python","optional":false}],"imports":[{"note":"The 'async' module was renamed to 'async_' in pyATS v19.0 (March 2019) due to 'async' becoming a reserved keyword in Python 3.7.","wrong":"from pyats.async import pcall","symbol":"pcall","correct":"from pyats.async_ import pcall"}],"quickstart":{"code":"import time\nfrom pyats.async_ import pcall\n\ndef my_cpu_bound_task(item):\n    \"\"\"A sample CPU-bound task that simulates work.\"\"\"\n    # print(f\"Starting task for item {item}...\") # Uncomment to see individual task starts\n    time.sleep(1) # Simulate some CPU-intensive work\n    result = item * item\n    # print(f\"Finished task for item {item}, result: {result}\") # Uncomment to see individual task finishes\n    return result\n\nif __name__ == \"__main__\":\n    items_to_process = [1, 2, 3, 4, 5]\n\n    print(\"\\n--- Running tasks in parallel with pcall ---\")\n    # pcall executes the function in parallel processes and returns results in order.\n    parallel_results = pcall(my_cpu_bound_task, *items_to_process)\n    print(f\"All parallel tasks completed. Results: {parallel_results}\")\n\n    print(\"\\n--- Running tasks synchronously for comparison ---\")\n    sync_results = [my_cpu_bound_task(item) for item in items_to_process]\n    print(f\"All synchronous tasks completed. Results: {sync_results}\")\n","lang":"python","description":"This quickstart demonstrates how to use `pcall` from `pyats.async_` to execute a CPU-bound function across multiple processes in parallel. It includes a synchronous comparison to highlight the benefits of parallel execution for such tasks."},"warnings":[{"fix":"Update your import statements from `from pyats.async import pcall` to `from pyats.async_ import pcall`.","message":"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.","severity":"breaking","affected_versions":"<19.0"},{"fix":"Run `pyats.async` applications on a supported Linux or Mac environment, or within a Linux-based virtual machine or Docker container on Windows.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Understand the distinction between multiprocessing (CPU-bound) and asyncio (I/O-bound). Use `pyats.async` primarily for tasks that will benefit from parallel execution across multiple CPU cores.","message":"`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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Change the import statement to `from pyats.async_ import pcall`.","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.","error":"ImportError: cannot import name 'pcall' from 'pyats.async'"},{"fix":"Implement 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.","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.","error":"TypeError: 'NoneType' object is not iterable (when using with pyATS topology/devices)"}]}