CLI#
Command-line tools for working with instro
instro ships a command-line interface for inspecting and discovering instruments on your bench.
Running the CLI#
The CLI comes with the instro package (see Installation).
In a project that has instro installed, run:
uv run instro discover
For regular use, put instro on your PATH instead so you can call it from anywhere:
uv tool install instro
instro discover
Usage#
instro –version#
Prints version information.
instro --version # prints version information
instro discover#
Scans all available VISA resources and serial ports, queries each instrument for its identity, and prints a summary table.
To force a specific VISA backend, pass --backend:
instro discover --backend=@py
instro discover --backend "@ivi"
Note
The @ivi backend finds an available IVI-compliant backend on your system e.g. NI-VISA or Keysight IO. @ivi is more reliable for USB and GPIB instruments. The @py backend (pyvisa-py) is a pure-Python fallback that works without NI-VISA installed but may not detect all instruments.
Output#
Before scanning, the command prints which VISA backend is active (@ivi, or @py when no IVI VISA is installed). On the @py backend it also lists any interfaces the scan cannot cover — for example GPIB: unavailable — gpib_ctypes is installed but could not locate the gpib library (install NI-488.2 or linux-gpib) — so you know when an empty result reflects a missing library rather than an empty bench. These notes are informational; the scan still runs and the command exits 0.
The command groups results into up to three tables.
Recognized devices — instruments with a known driver. The table shows the VISA resource address, instrument category, and the instro driver class to use.
Serial devices — serial ports detected by the OS. These are listed separately because serial instruments require manual configuration; instro discover cannot query them automatically.
Unrecognized devices — instruments that responded to *IDN? but did not match any known driver. The raw IDN response is shown so you can identify the device.
If no devices are found at all, the command prints a single error panel; on the @py backend the panel repeats any unavailable interfaces.
Using a recognized device#
Pass the resource address from the Recognized devices table directly to the driver’s constructor:
from instro.psu.drivers.bk_9115 import BK9115
from instro.psu import InstroPSU
psu = InstroPSU(name="psu", driver=BK9115("USB0::0x15EF::0x0099::INSTR"), num_channels=1)
psu.open()
Unrecognized devices#
If your instrument appears in the Unrecognized devices table, instro does not yet have a driver for it. See Custom instruments for how to author one, or instro-contrib to check for community-contributed drivers.
Discovering programmatically#
instro discover is a thin wrapper around scan_visa_resources, which is also available directly from instro.lib for use in your own scripts:
from instro.lib import scan_visa_resources
result = scan_visa_resources()
for info in result.instruments:
print(info.resource, info.category, info.driver_name)
for unrecognized in result.unrecognized:
print(unrecognized.resource, unrecognized.idn)
for error in result.errors:
print(error.resource, error.hint or error.message)
scan_visa_resources accepts the same backend the CLI’s --backend flag does, plus an optional timeout (seconds per instrument query, default 2) that the CLI doesn’t currently expose. It returns a VisaScanResult with instruments (DiscoveredInstrument), unrecognized (VisaUnrecognizedInstrument), and errors (VisaScanError) — the same data the CLI renders into the tables above.
Each DiscoveredInstrument can build what you need next, so a script never re-derives the driver from the resource string:
from instro.psu import InstroPSU
psu_info = next(i for i in result.instruments if i.category == "psu")
# a ready-to-open driver (VisaConfig with the backend the scan was asked for)
psu = InstroPSU(name="psu", driver=psu_info.make_driver(), num_channels=psu_info.num_channels)
# or the ``driver`` block of a JSON config, for InstroPSU(config=...)
driver_block = psu_info.config_block()
visa_config() returns the VisaConfig on its own, and driver_class() the driver class, when you want to construct the driver yourself.