Migrating from Legacy Systems

Migrer de LabVIEW vers Python

Un guide pratique pour remplacer LabVIEW par Python pour l'automatisation des tests de fabrication, avec des correspondances de concepts, des exemples de.

JJulien Buteau
intermediate14 min de lecture14 mars 2026

LabVIEW est puissant, mais il s'accompagne de licences à 3 000-5 000 $/poste, d'un déploiement Windows uniquement et de fichiers binaires mal adaptés au contrôle de version. Python vous offre les mêmes capacités de contrôle d'instruments sans coût de licence, avec un support multiplateforme et une intégration Git native. Ce guide fait correspondre les concepts LabVIEW à leurs équivalents Python et vous montre comment reconstruire votre système de test avec OpenHTF et TofuPilot.

Pourquoi les équipes migrent

Point de frictionLabVIEWPython
Coût de licence3 160-4 840 $/poste/an (selon l'édition)Gratuit
DéploiementWindows uniquementLinux, macOS, Windows
Contrôle de versionFichiers binaires .vi, conflits de fusionFichiers texte, natif Git
RecrutementLes développeurs LabVIEW sont rares et coûteuxLes développeurs Python sont partout
CI/CDDifficile à intégrerNatif (pytest, GitHub Actions, etc.)
Écosystème de packagesPackages NI + communauté limitéepip, PyPI, 400 000+ packages
Revue de codeNécessite LabVIEW pour visualiserN'importe quel éditeur de texte
CollaborationUne personne par VI à la foisWorkflow Git standard

Correspondance des concepts LabVIEW vers Python

Concept LabVIEWÉquivalent PythonNotes
VI (Virtual Instrument)Fonction PythonMême idée : unité réutilisable et appelable
SubVIFonction ou méthode de classeImport depuis un module
Face-avantPas d'équivalent (ou : tableau de bord TofuPilot)Python n'a pas besoin d'interface graphique par fonction
DiagrammeCode PythonDu texte au lieu de fils
Panneau de connecteursSignature de fonctiondef measure_voltage(channel: int) -> float
Cluster d'erreurGestion d'exceptionstry/except au lieu de fils d'erreur
TypedefClasse ou dataclass@dataclass pour les données structurées
Variable globaleVariable au niveau module ou attribut de classeÀ éviter dans la mesure du possible
Nœud de propriétéDécorateur property@property sur une classe
Machine d'étatsClasse avec méthodes ou match/caseVoir l'exemple ci-dessous
Fichier TDMSJSON, CSV ou TofuPilotTofuPilot remplace la journalisation fichier
Pilote DAQmxPyVISA + pyvisa-pyOu package Python nidaqmx
Pilote d'instrumentPlug OpenHTFBasePlug avec setUp/tearDown
Séquence de testTest OpenHTFhtf.Test(phase1, phase2, ...)

Étape 1 : Configurer votre environnement Python

migration/setup.sh
python -m venv venv
source venv/bin/activate    # Linux/macOS
# venv\Scripts\activate     # Windows

pip install openhtf tofupilot pyvisa pyvisa-py

Cela vous donne :

  • openhtf : Framework de test (remplace le séquenceur de test LabVIEW)
  • tofupilot : Analyses cloud (remplace la journalisation fichier TDMS)
  • pyvisa : Contrôle d'instruments (remplace les pilotes d'instruments LabVIEW)

Étape 2 : Convertir les SubVI en fonctions Python

Un SubVI LabVIEW qui lit la tension d'un DMM devient une fonction Python :

migration/instrument_functions.py
def measure_voltage(channel: int) -> float:
    """Équivalent d'un SubVI LabVIEW qui lit la tension d'un DMM.

    En LabVIEW : SubVI avec entrée canal (I32) et sortie tension (DBL).
    En Python : fonction avec annotations de type.
    """
    readings = {1: 3.31, 2: 5.02, 3: 1.81}  # Remplacer par de vraies lectures
    return readings.get(channel, 0.0)


# L'appeler comme on câblerait un SubVI
rail_3v3 = measure_voltage(1)
rail_5v0 = measure_voltage(2)

La signature de la fonction remplace le panneau de connecteurs. Les annotations de type (int, float) remplacent les types de données LabVIEW.

Étape 3 : Remplacer le cluster d'erreur

LabVIEW utilise un cluster d'erreur (status, code, source) câblé à travers chaque VI. Python utilise les exceptions.

migration/error_handling.py
class InstrumentError(Exception):
    """Remplace le cluster d'erreur LabVIEW pour les erreurs d'instrument."""

    def __init__(self, code: int, source: str, message: str):
        self.code = code
        self.source = source
        super().__init__(f"[{code}] {source}: {message}")


# LabVIEW : vérifier le cluster d'erreur à chaque nœud
# Python : try/except attrape les erreurs de n'importe où dans le bloc
try:
    voltage = measure_voltage(1)
    if voltage < 0:
        raise InstrumentError(1001, "DMM", "Lecture de tension négative")
except InstrumentError as e:
    print(f"Erreur d'instrument : {e}")
    # Gérer ou relancer

C'est plus propre que de câbler des clusters d'erreur à travers chaque nœud. Les exceptions se propagent automatiquement jusqu'à ce qu'elles soient attrapées.

Étape 4 : Remplacer la machine d'états

Les machines d'états LabVIEW utilisent une boucle while + structure case. Python offre plusieurs options.

migration/state_machine.py
class TestSequencer:
    """Remplace une machine d'états LabVIEW pour le séquencement de tests."""

    def __init__(self):
        self.results = {}
        self.state = "init"

    def run_step(self, name: str, func, limits: tuple) -> bool:
        """Exécuter une étape de test et enregistrer le résultat."""
        value = func()
        passed = limits[0] <= value <= limits[1]
        self.results[name] = {
            "value": value,
            "limits": limits,
            "passed": passed,
        }
        return passed

    def run(self):
        """Exécuter la séquence de test complète."""
        self.run_step("rail_3v3", lambda: 3.31, (3.2, 3.4))
        self.run_step("rail_5v0", lambda: 5.02, (4.8, 5.2))

        all_passed = all(r["passed"] for r in self.results.values())
        return all_passed


seq = TestSequencer()
passed = seq.run()
print(f"Test {'RÉUSSI' if passed else 'ÉCHOUÉ'}")

Mais vous n'avez pas besoin de construire cela vous-même. OpenHTF gère le séquencement, les mesures et les limites nativement.

Étape 5 : Utiliser OpenHTF au lieu de construire un séquenceur

OpenHTF remplace à la fois le séquenceur de test LabVIEW et la journalisation des données (TDMS). Les pilotes d'instruments deviennent des Plugs.

migration/openhtf_test.py
import openhtf as htf
from openhtf.plugs import BasePlug
from openhtf.util import units
from tofupilot.openhtf import TofuPilot


class InstrumentPlug(BasePlug):
    """Remplace les VI de pilote d'instrument LabVIEW.

    setUp = équivalent de l'ouverture d'une session VISA dans LabVIEW
    méthodes = équivalent des SubVI pour chaque mesure
    tearDown = équivalent de la fermeture de session
    """

    def setUp(self):
        self._voltages = iter([3.31, 5.02])
        # Remplacer par : rm = pyvisa.ResourceManager("@py")
        # self.instr = rm.open_resource("TCPIP::192.168.1.100::INSTR")

    def read_voltage(self) -> float:
        return next(self._voltages)
        # Remplacer par : return float(self.instr.query(":MEAS:VOLT:DC?"))

    def tearDown(self):
        pass
        # Remplacer par : self.instr.close()


@htf.measures(
    htf.Measurement("rail_3v3")
    .in_range(3.2, 3.4)
    .with_units(units.VOLT)
    .doc("Rail 3,3 V"),
    htf.Measurement("rail_5v0")
    .in_range(4.8, 5.2)
    .with_units(units.VOLT)
    .doc("Rail 5,0 V"),
)
@htf.plug(instr=InstrumentPlug)
def test_power_rails(test, instr):
    """Remplace une séquence de test LabVIEW avec des Numeric Limit Tests."""
    test.measurements.rail_3v3 = instr.read_voltage()
    test.measurements.rail_5v0 = instr.read_voltage()


def main():
    test = htf.Test(
        test_power_rails,
        procedure_id="FCT-001",
        part_number="PCBA-100",
    )
    with TofuPilot(test):
        test.execute(test_start=lambda: input("Scanner le numéro de série : "))


if __name__ == "__main__":
    main()

Étape 6 : Remplacer TDMS par TofuPilot

LabVIEW écrit les données de test dans des fichiers TDMS. Vous devez ensuite construire vos propres outils d'analyse pour les lire. TofuPilot remplace l'ensemble de cette chaîne.

LabVIEW (TDMS)TofuPilot
Écrire un fichier TDMS après chaque testUpload automatique (une ligne de code)
Construire des outils d'analyse personnalisésTableau de bord avec FPY, Cpk, cartes de contrôle
Agrégation manuelle des données entre postesAgrégation multi-postes automatique
Serveur de fichiers pour le stockage TDMSStockage cloud avec accès API
Génération de rapports personnalisésRapports et exports intégrés

Checklist de migration

ÉtapeActionÉquivalent LabVIEW
1Installer Python + venvInstaller LabVIEW
2pip install openhtf tofupilot pyvisaInstaller les packages NI
3Créer des classes Plug pour chaque instrumentCréer les VI de pilote d'instrument
4Écrire les fonctions de phase avec @htf.measuresCréer la séquence de test avec vérification des limites
5Assembler htf.Test() avec toutes les phasesConstruire la séquence de test dans LabVIEW
6Ajouter with TofuPilot(test)Configurer la journalisation TDMS
7Exécuter et valider que les résultats concordent avec LabVIEWComparer les valeurs de mesure

Pièges courants

PiègeSolution
« La face-avant me manque »Utilisez le tableau de bord TofuPilot pour le suivi en temps réel. Pour l'interface opérateur, OpenHTF a une interface web intégrée.
« Mon matériel NI nécessite des pilotes NI »Utilisez le package Python nidaqmx pour le matériel DAQmx. Pour GPIB, installez le runtime NI-VISA.
« LabVIEW gère le threading automatiquement »Python a le threading et asyncio. OpenHTF gère le threading d'exécution des phases.
« Mon équipe ne connaît pas Python »Python a une courbe d'apprentissage plus douce que LabVIEW. La plupart des ingénieurs l'apprennent en jours, pas en semaines.
« Nous avons des années de code LabVIEW »Migrez de manière incrémentale. Commencez par les nouveaux tests en Python. Convertissez les tests existants un par un.

Plus de guides

Mettez ce guide en pratique