8.4.2. Hardware Discovery

PyMoDAQ provides a shared, process-lifetime cache for enumerating hardware resources. Each backend is queried at most once per process; every plugin that imports from pymodaq_plugins_utils.hardware reuses the same cached result.

Both pyvisa and pyserial are optional dependencies. If a backend is not installed, the corresponding functions return empty lists silently — no exception is raised.

See also

Shared hardware discovery in the plugin development tutorial for migration examples.

8.4.2.1. Base cache class

class pymodaq_plugins_utils.hardware.base.HardwareCache[source]

Base class for process-lifetime hardware discovery caches.

Each subclass calls its backend (pyvisa, pyserial, …) exactly once per process. The result is stored as a class variable and reused by every caller, regardless of which plugin package triggered the first call.

Subclasses must override _fetch() and list_resources(). Call invalidate_cache() to force re-discovery, for example after hot-plugging a device.

Example — defining a new backend:

class MyCache(HardwareCache):
    _cache = None

    @classmethod
    def _fetch(cls):
        return some_expensive_os_call()

    @classmethod
    def list_resources(cls) -> list[str]:
        return [item.id for item in cls._get_cache()]

Methods

invalidate_cache()

Clear the cache so the next call to any list_* method re-discovers.

list_resources()

Return a list of connectable resource strings for this backend.

classmethod invalidate_cache()[source]

Clear the cache so the next call to any list_* method re-discovers.

Use this after hot-plugging a device or when the set of available instruments may have changed since process startup.

Return type:

None

classmethod list_resources()[source]

Return a list of connectable resource strings for this backend.

Return type:

list[str]

8.4.2.2. VISA resources

VISA hardware discovery cache.

Wraps pyvisa to enumerate available VISA resources exactly once per process. pyvisa is an optional dependency: if it is not installed, or no VISA backend is found, all functions return empty lists and a warning is logged.

Typical usage in a plugin:

from pymodaq_utils.hardware.visa import list_serial_resources

ports = list_serial_resources()  # e.g. ['ASRL/dev/ttyUSB0::INSTR']

After hot-plugging a device, refresh the cache with:

from pymodaq_utils.hardware.visa import invalidate_cache
invalidate_cache()
pymodaq_plugins_utils.hardware.visa.invalidate_cache()[source]

Clear the VISA resource cache so the next call re-discovers.

Return type:

None

pymodaq_plugins_utils.hardware.visa.list_resource_aliases()[source]

Human-readable aliases where available (e.g. 'COM3' on Windows).

Return type:

list[str]

pymodaq_plugins_utils.hardware.visa.list_resources()[source]

All available VISA resource strings (e.g. ‘GPIB0::5::INSTR’, ‘TCPIP0::…’).

Return type:

list[str]

pymodaq_plugins_utils.hardware.visa.list_serial_resources()[source]

ASRL (serial-over-VISA) resource strings only.

Linux: 'ASRL/dev/ttyUSB0::INSTR' Windows: 'ASRL3::INSTR'

Return type:

list[str]

8.4.2.3. Serial ports

pyserial hardware discovery cache.

Wraps serial.tools.list_ports to enumerate available serial ports exactly once per process. pyserial is an optional dependency: if it is not installed, all functions return empty lists and a warning is logged.

Typical usage in a plugin:

from pymodaq_utils.hardware.serial_ports import list_resources

ports = list_resources()  # e.g. ['/dev/ttyUSB0', 'COM3']

After hot-plugging a device, refresh the cache with:

from pymodaq_utils.hardware.serial_ports import invalidate_cache
invalidate_cache()
pymodaq_plugins_utils.hardware.serial_ports.invalidate_cache()[source]

Clear the serial port cache so the next call re-discovers.

Return type:

None

pymodaq_plugins_utils.hardware.serial_ports.list_port_descriptions()[source]

Human-readable descriptions for each serial port.

Return type:

list[str]

pymodaq_plugins_utils.hardware.serial_ports.list_resources()[source]

Serial port device strings (e.g. ‘/dev/ttyUSB0’, ‘COM3’).

Return type:

list[str]

8.4.2.4. Package helpers

Hardware discovery caches for PyMoDAQ plugins.

Each backend (visa, serial_ports) queries the OS exactly once per process. Subsequent calls reuse the cached result, so plugin startup cost is paid at most once regardless of how many plugins share the same backend.

Quick reference:

# VISA-based plugin (Newport, Thorlabs, PI, ...)
from pymodaq_utils.hardware.visa import list_serial_resources
ports = list_serial_resources()

# pyserial-based plugin (Arduino, Ocean Optics, ...)
from pymodaq_utils.hardware.serial_ports import list_resources
ports = list_resources()

# After hot-plugging a device
from pymodaq_utils.hardware import invalidate_all_caches
invalidate_all_caches()
pymodaq_plugins_utils.hardware.invalidate_all_caches()[source]

Clear both the VISA and serial discovery caches.

Call this after hot-plugging a device so the next call to any list_* function re-discovers the current set of instruments.

Return type:

None