Install & Compatibility
Where this runs
tested against v26.5 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
879MB installed
● package 879MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
aetest
✓ from pyats import aetest
Core pyATS test infrastructure module for defining test cases and sections.
loader
✓ from pyats.topology import loader
Used for loading testbed YAML files into Python objects.
load
✓ from genie.testbed import load
Specifically for loading Genie testbed files. This is commonly used in conjunction with pyATS for network device interaction. [3]
run
✓ from pyats.easypy import run
Used for executing pyATS jobs and scripts within the EasyPy runtime environment. [20]
ConnectionError
✓ from unicon.core.errors import ConnectionError
For handling connection-related exceptions when interacting with devices. [20]
This quickstart demonstrates a basic pyATS test script. It defines a testcase with setup, test, and cleanup sections. The setup loads a testbed file (e.g., `testbed.yaml`) which describes the network devices and their connection details, including credentials often sourced from environment variables. The test section connects to a device, executes a 'show version' command, and then uses Genie's `parse()` method to get structured data from 'show ip interface brief'. Ensure `testbed.yaml` is configured with valid device IPs and credentials are set as environment variables (e.g., `PYATS_TESTBED_USERNAME`, `PYATS_TESTBED_PASSWORD`). The script includes a dummy `testbed.yaml` creation for local execution. Run with `python your_script_name.py` or `pyats run job your_script_name.py`. [3, 8, 20, 25]
import os
import logging
from pyats import aetest
from genie.testbed import load
from unicon.core.errors import ConnectionError
# Set up basic logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Create a dummy testbed file (testbed.yaml) for demonstration
# In a real scenario, this would describe your network devices.
# For a live environment, set environment variables for credentials:
# export PYATS_TESTBED_USERNAME='your_username'
# export PYATS_TESTBED_PASSWORD='your_password'
# Example content for testbed.yaml:
# devices:
# CSR1:
# os: iosxe
# connections:
# cli:
# protocol: ssh
# ip: 10.1.1.1 # Replace with your device IP
# credentials:
# default:
# username: '%ENV{PYATS_TESTBED_USERNAME}'
# password: '%ENV{PYATS_TESTBED_PASSWORD}'
class MyFirstTest(aetest.Testcase):
@aetest.setup
def setup(self, testbed):
# Load the testbed from a YAML file
try:
self_testbed = load(os.path.join(os.path.dirname(__file__), 'testbed.yaml'))
self.parent.parameters.update(testbed=self_testbed)
logger.info(f"Testbed loaded successfully: {list(self_testbed.devices.keys())}")
except Exception as e:
self.failed(f"Failed to load testbed: {e}")
@aetest.test
def connect_and_execute(self, testbed):
if not hasattr(self.parent.parameters, 'testbed'):
self.skipped('Testbed not loaded in setup.')
return
for device_name, device in self.parent.parameters['testbed'].devices.items():
logger.info(f"Attempting to connect to device: {device_name}")
try:
device.connect(init_exec_params={'timeout': 60})
logger.info(f"Successfully connected to {device_name}")
# Example: Execute a 'show version' command
output = device.execute('show version')
logger.info(f"Output from {device_name}:\n{output[:200]}...") # Print first 200 chars
# Example: Parse 'show ip interface brief'
parsed_output = device.parse('show ip interface brief')
logger.info(f"Parsed output from {device_name} (first entry): {list(parsed_output.values())[0] if parsed_output else 'No interfaces found'}")
self.passed(f"Successfully connected, executed, and parsed on {device_name}")
except ConnectionError as e:
self.failed(f"Connection failed for {device_name}: {e}")
except Exception as e:
self.failed(f"An error occurred with {device_name}: {e}")
finally:
if device.is_connected():
device.disconnect()
logger.info(f"Disconnected from {device_name}")
@aetest.cleanup
def cleanup(self):
logger.info("Testcase cleanup completed.")
if __name__ == '__main__':
import sys
# Create a dummy testbed.yaml for local execution if it doesn't exist
testbed_path = os.path.join(os.path.dirname(__file__), 'testbed.yaml')
if not os.path.exists(testbed_path):
with open(testbed_path, 'w') as f:
f.write("""
---
devices:
CSR1:
os: iosxe
connections:
cli:
protocol: ssh
ip: 10.1.1.1 # REPLACE WITH YOUR DEVICE IP OR A MOCK IP FOR TESTING
credentials:
default:
username: '%ENV{PYATS_TESTBED_USERNAME}'
password: '%ENV{PYATS_TESTBED_PASSWORD}'
""")
logger.warning(f"Created a dummy '{testbed_path}'. Please replace 10.1.1.1 with a real device IP and set environment variables PYATS_TESTBED_USERNAME and PYATS_TESTBED_PASSWORD.")
# Set dummy env vars if not present for local execution to avoid crashes
os.environ.setdefault('PYATS_TESTBED_USERNAME', 'admin')
os.environ.setdefault('PYATS_TESTBED_PASSWORD', 'password')
# Run the AETest
aetest.main(argv=sys.argv)
pyats --version
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'pyats.topology'
pyATS or its sub-packages are not installed, or the current Python environment is not the one where pyATS was installed. [21]
fixEnsure you are in the correct Python virtual environment (if used) and install pyATS: `pip install 'pyats[full]'`. Verify installation with `pyats version check`. [21]
ConnectionError: Failed to connect to device 'my_device'
This generic error indicates a problem establishing a connection to the network device. Common causes include incorrect IP address/hostname, firewall blocking, incorrect credentials, device not reachable, or device hostname mismatch in the testbed file. [10, 20]
fixDouble-check the IP address and credentials in your `testbed.yaml`. Ping the device to verify reachability. Ensure the device name in `testbed.yaml` exactly matches the device's configured hostname. Verify SSH/Telnet access manually. [10]
AttributeError: 'Device' object has no attribute 'parse'
The Genie library, which provides the `parse` method for structured output, might not be fully installed or accessible. This typically happens with a minimal `pyats` installation without `genie`. [14]
fixEnsure you have installed pyATS with the `[library]` or `[full]` extra, which includes Genie: `pip install 'pyats[full]'`. [5, 14]
ERROR: Could not find a version that satisfies the requirement pyats[full] (from versions: none)
This usually means pip cannot find the package, often due to network issues (e.g., corporate proxy) or a misspelled package name. [21]
fixCheck your internet connection. If behind a corporate proxy, configure pip to use it: `pip install --proxy http://proxy.company.com:8080 'pyats[full]'` or set `HTTP_PROXY`/`HTTPS_PROXY` environment variables. Also, ensure the package name is spelled correctly. [21]
Upgrade
Version history
26.5latest on PyPI · released May 28, 2026
Audit
Dependencies
genierequiredGenie is the core library within the pyATS ecosystem for parsing device output into structured data and providing platform/vendor agnostic support. It is usually installed as part of pyats[full] or pyats[library]. [3, 11, 14]