Free tech learning for everyone, from basics to pro

Network AutomationProgramming and Application SecurityIntermediate

Nornir: running Python tasks across many network devices in parallel

In short: Nornir is a Python automation framework that runs tasks against many devices in parallel. It reads hosts and groups from an inventory, lets you filter targets, and uses plugins such as Netmiko and NAPALM to do the work. Everything is plain Python, so logic and debugging are straightforward.

Why a framework?

Looping over devices one by one is fine for five switches, but slow for five hundred. You also end up rewriting the same inventory loading, threading and error handling in every script. Nornir is an open-source Python framework that provides those pieces: an inventory, a way to filter it, a runner that works on many hosts in parallel, and a result object that records what happened on each host.

Nornir building blocksNornirPython frameworkInventoryhosts, groupsTasksPython functionsRunnerthreads in parallelFilterspick targetsPluginsNetmiko, NAPALMResultsper-host output
Figure 1. Nornir combines an inventory, tasks and a parallel runner, extended with plugins.

Inventory and configuration

The default SimpleInventory plugin reads YAML files. Hosts inherit settings from groups and defaults, so you only write shared values once. Install the packages with pip install nornir nornir-utils nornir-netmiko.

# config.yaml
inventory:
  plugin: SimpleInventory
  options:
    host_file: inventory/hosts.yaml
    group_file: inventory/groups.yaml
runner:
  plugin: threaded
  options:
    num_workers: 20
# inventory/hosts.yaml
acc-sw1:
  hostname: 192.168.10.11
  groups: [ios]
  data:
    site: london
    role: access
core-sw1:
  hostname: 192.168.10.1
  groups: [ios]
  data:
    site: london
    role: core
# inventory/groups.yaml
ios:
  platform: cisco_ios

Tasks, filters and results

A task is a Python function that receives a Task object for one host. You can call plugin tasks inside it, or write your own logic. The runner calls it for every host in the filtered inventory at the same time, up to num_workers.

import os
from nornir import InitNornir
from nornir.core.task import Task, Result
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result

nr = InitNornir(config_file="config.yaml")
nr.inventory.defaults.username = os.environ["NET_USER"]
nr.inventory.defaults.password = os.environ["NET_PASS"]


def check_version(task: Task) -> Result:
    r = task.run(task=netmiko_send_command, command_string="show version")
    ok = "15.2" not in r.result
    return Result(host=task.host, result="ok" if ok else "old software")


access = nr.filter(site="london", role="access")
results = access.run(task=check_version)
print_result(results)

for host, multi in results.items():
    if multi.failed:
        print(host, "FAILED:", multi.exception)

Tip: failed hosts are recorded, not fatal. Check results.failed_hosts after a run, and use nr.data.failed_hosts to retry only those that failed.

Choosing Nornir and using it well

Nornir and AnsibleNornirPure PythonLogic in normal codeDebug with Python toolsVery fast at scaleAnsibleYAML playbooksLarge module libraryEasier for non-codersStrong ecosystem, AWX
Figure 2. Nornir suits teams comfortable in Python; Ansible suits teams preferring declarative YAML.
  • Keep tasks small: one task to gather facts, one to render a template, one to push it. Compose them inside a parent task.
  • Use dry runs: plugins such as napalm_configure accept dry_run=True to show the difference without committing.
  • Tune workers: too many parallel sessions can overload a TACACS+ or RADIUS server or the devices. Start with 10 to 20.
  • Source of truth: inventory plugins exist for NetBox and other systems, so Nornir can read devices straight from your IPAM (IP address management) tool.
  • Secrets: set credentials at run time from environment variables or a vault, never in hosts.yaml.

Practice

What does the threaded runner’s num_workers control?
How many hosts Nornir works on at the same time.
A task fails on two of fifty hosts. What happens to the other forty-eight?
They complete normally. Nornir records the two failures in the results, and you can inspect or retry them afterwards.
How would you run a task only on core switches in one site?
Use nr.filter() with the matching data fields, for example nr.filter(site="london", role="core"), then call run() on the filtered object.

Key takeaways

  • Nornir is a pure-Python framework for parallel network automation.
  • Inventory hosts inherit from groups and defaults.
  • Tasks are Python functions; plugins add Netmiko, NAPALM and more.
  • Filter targets, then inspect per-host results and failures.
  • Set credentials at run time and tune worker counts sensibly.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.