Skip to main content
RunBook Academy

AnsibleXLVI · Python and Interpreter DiscoveryRemote Python and interpreter discovery

Targets that cannot run Python

Advanced⏱ ~18 minansible-coreansible-doc

What you'll learn

  • Distinguish a host that has no Python yet from one that will never have Python
  • Explain why command and shell are not available on such hosts
  • State what raw and script can and cannot give you, including for check mode and idempotency
  • Choose between raw, a vendor collection and leaving a host out of scope
  • Set expectations for an estate that includes appliances, without pretending they are servers

Prerequisites

Verified against ansible-core 2.21.x · ansible (community package) 14.x · Python (controller) 3.12+ · ansible-lint 26.x · Molecule 26.x · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL / Rocky / AlmaLinux 9.x · 2026-08-11

Not yet marked complete on this device.

The previous lesson dealt with a host that has no Python yet. This one deals with a host that will never have one.

The distinction matters more than it sounds, because the two look identical in the output of a failed run and have completely different answers. One is a bootstrap problem with a three-task solution. The other is a scope decision, and pretending otherwise produces the worst automation in an estate.

Which hosts are these

Three families, with different reasons.

Network and storage appliances. A switch, a load balancer, a firewall appliance, a storage controller. These run a vendor operating system with a restricted shell. There is no package manager you are permitted to use, no filesystem you are supposed to write to, and often no general-purpose shell at all — you get a command-line interface that looks like a shell and is not one.

Minimal container images. A distroless image, or a scratch image with a single static binary. Python is absent because the whole point of the image is that nothing is present. This is a design success, not a gap to be filled.

Embedded and appliance-like Linux. Routers running a BusyBox userland, industrial controllers, storage appliances with a manufacturer-supported firmware image. Python may be technically installable and installing it may void support, break the next firmware update, or exhaust the filesystem.

The common thread is that “install Python” is not available to you — not because it is hard, but because it is the wrong action.

The trap: command and shell are not an escape hatch

This is the single most common mistake in this area, and it is worth stating as bluntly as the course can manage.

ansible.builtin.command and ansible.builtin.shell run on the target using Python. They are ordinary modules. They ship a payload, that payload is executed by an interpreter, and the interpreter invokes a subprocess. The subprocess is the part you were thinking of; the three steps before it are the part that fails.

The reasoning that leads people astray is entirely sensible — “it runs a shell command, so surely it needs a shell and not Python” — and it is wrong. The check is one command:

Read-only / Safewhich builtin actions genuinely need no interpreter
$ ansible-doc ansible.builtin.raw | grep -A4 'platform:'
        platform:
      description: Target OS/families that can be operated against
      details: This action is one of the few that requires no Python on the remote as it
        passes the command directly into the connection string
      platforms: all

The same documentation for ansible.builtin.script states that it “does not require Python on the remote system, much like the ansible.builtin.raw module”. Those two, and nothing else in ansible.builtin.

What raw and script honestly give you

Both work. Neither gives you what modules give you, and the gap is not small.

Normal moduleraw / script
Check modesupported by mostnone
Diff modesupported by manynone
Idempotencymodule’s jobyours, by hand
Change detectionrealwhatever you assert
Structured returnJSON fieldsstdout, stderr, rc
Error semanticsmodule-definedexit code only

The raw module’s own attributes record check_mode: support: none and diff_mode: support: none on 2.21.3. That is not a documentation gap — it is a statement that a --check run against these hosts tells you nothing, because the task is skipped rather than simulated.

What automation of these hosts actually looks like

Three honest options, in the order you should consider them.

Use the vendor’s collection. Network vendors ship collections that speak the device’s own API or CLI over an appropriate connection plugin, and they run the module logic on the controller rather than on the device. That is the design that makes structured, idempotent automation of a device with no Python possible at all, and it is why network automation with Ansible is a real discipline rather than a pile of raw tasks. If a collection exists for your device, it is almost always the right answer, and Part XXVII’s guidance on evaluating third-party collections applies unchanged.

Use raw or script, deliberately and narrowly. For a device with no collection, a small number of well-understood commands, wrapped with your own changed_when and failed_when, in their own play, is defensible. Write down what makes each task idempotent, because nothing in the code will say.

Leave the host out of scope, explicitly. This is a legitimate engineering decision and it is under-used. A host managed by a different team through a different tool is not a failure of your automation; a host that appears in your inventory, fails every run, and is ignored by everyone is. If you are not going to automate it, remove it from the inventory the automation runs against and record why.

Knowledge check

Knowledge check · 4 questions

  1. Q1. A task using ansible.builtin.command fails against a network appliance with a vendor syntax error, but the same command via ansible.builtin.raw succeeds. What does that tell you?

  2. Q2. Why can a vendor network collection offer idempotency and check mode on a device that cannot run a Python module?

  3. Q3. Which are accurate about raw and script on ansible-core 2.21.3? Select all that apply.

  4. Q4. Leaving an unautomatable appliance out of the inventory your automation runs against is a legitimate engineering decision rather than an admission of failure.

Passing score: 75%. Answers are checked in this browser.