Automatiser l’impression d’étiquettes avec des scripts de champ Python
L’étiquette est presque correcte à chaque fois. La date est obsolète, le numéro de série a perdu ses zéros initiaux, et le total a besoin d’une clé de contrôle avant que le code-barres ne puisse être scanné. Alors quelqu’un ouvre le modèle d’étiquette dans l’éditeur, modifie trois champs, lance l’impression, puis refait exactement la même chose le lendemain matin.
Cette modification n’a pas sa place dans un modèle. Elle appartient au code qui s’exécute au moment de l’impression. RSJ LPSNG vous permet d’attacher un bloc de script Python directement à un champ d’étiquette, de sorte que la transformation s’effectue à l’intérieur du modèle — pas d’étape de prétraitement, pas de rituel « corriger d’abord le CSV » entre votre ERP et l’imprimante.
Cet article porte sur l’automatisation au niveau du champ : ce qu’est un script de champ, comment le configurer une fois pour toutes, comment le piloter depuis l’API du service web, et comment l’empêcher de casser silencieusement votre ligne de production.
Deux sujets connexes sont traités ailleurs : le contenu qui change à chaque commande est abordé dans Building Order-Specific Labeling on Top of a Label Printing API, et les étiquettes pilotées par les données issues de feuilles de calcul dans How to Create Labels from Excel Data Files and Lookup Tables. Ici, nous restons sur le champ.
Pourquoi automatiser l’impression d’étiquettes avec des scripts de champ Python ?
Les scripts de champ s’exécutent à l’intérieur du modèle d’étiquette. Le bloc Python est attaché à un champ et accède à la valeur actuelle de ce champ, qu’il peut modifier avant le rendu de l’étiquette. Cette seule décision de conception change le pipeline :
- Pas de prétraitement externe. Vous n’avez pas besoin d’un script qui réécrit vos données d’entrée avant de les soumettre. Les données arrivent telles quelles ; l’étiquette corrige ce qui doit l’être.
- Cohérence entre les clients. Le script voyage avec l’étiquette. Que la tâche provienne de l’interface web, de l’API du service web ou du LPSNG Player, le même champ reçoit le même traitement.
- La logique est vérifiable. Elle se trouve à côté du champ qu’elle affecte, et non dans une tâche cron sur l’ordinateur portable de quelqu’un.
Les tâches qui justifient cela sont ennuyeuses et répétitives :
| Tâche | Approche manuelle | Script de champ |
|---|---|---|
| Horodatage d’impression | Saisir la date du jour dans le champ | Formater la valeur au moment du rendu |
| Numéros de série | Compléter à la main, en oublier un, réimprimer | Normaliser à une largeur fixe |
| Clés de contrôle | Calculer dans un tableur | Calculer à partir de la valeur du champ |
| Étiquettes dérivées | Copier une valeur depuis un autre champ | Référencer le champ source |
Aucune de ces tâches n’est difficile. C’est justement le point — elles sont trop petites pour mériter un service, et trop fréquentes pour continuer à les faire à la main.
Configuration initiale : préparer votre étiquette et votre script
La configuration est une tâche unique par champ. Vous avez besoin du studio d’étiquettes, pas d’un environnement Python local.
- Ouvrez l’étiquette que vous souhaitez automatiser dans le studio d’étiquettes LPSNG et sélectionnez le champ. Choisissez un champ associé à un élément texte ou code-barres.
- Attachez un bloc de script Python à ce champ via l’API de script de champ. Le script est stocké et géré par la plateforme aux côtés de l’étiquette — il n’y a aucun interpréteur à installer sur le client d’impression.
- Utilisez le contexte du script. Le bloc voit la valeur actuelle du champ et en renvoie une version modifiée avant l’impression. Les variables de contexte exactes sont définies dans la référence de l’API Python — lisez-la une fois, puis copiez le modèle.
- Enregistrez l’étiquette. Désormais, chaque tâche qui effectue le rendu de cette étiquette exécute le script.
Un bloc minimal qui normalise un numéro de série :
# Field: serial
# Runs before rendering. Input: the value passed in the print job.
raw = str(value).strip()
if raw.isdigit():
value = f"SN-{int(raw):06d}"
else:
value = raw.upper()
Et un autre qui appose l’heure d’impression plutôt que de faire confiance aux données :
# Field: printed_at
from datetime import datetime
value = datetime.now().strftime("%Y-%m-%d %H:%M")
L’intérêt de faire cela dans une plateforme gérée plutôt que dans votre propre code, c’est que le script fait partie de l’étiquette : il est versionné avec elle, réutilisé entre les tâches et ne peut pas se désynchroniser du modèle.
La réutilisation est le véritable bénéfice. Une fois qu’un script est correct, attachez le même bloc à chaque champ qui nécessite la même transformation — sur tous les modèles, sur toutes les imprimantes. Dix modèles d’étiquettes qui impriment tous les numéros de série de la même manière sont dix modèles qui échouent tous de la même manière, et un seul endroit où corriger.
Construire le pipeline automatisé : des données à l’impression
Une fois le script attaché, le pipeline est le suivant : s’authentifier, soumettre une tâche d’impression, laisser l’étiquette faire le travail.
S’authentifier une fois
L’interface de service web de LPSNG utilise OAuth2 avec un protocole d’enregistrement simplifié qui connecte un système externe à l’aide d’une seule URL. Effectuez l’enregistrement une fois, stockez le jeton dans votre coffre de secrets et gardez-le hors de votre dépôt :
export LPSNG_BASE_URL="https://lpsng.rsj.de" # host of your edition
export LPSNG_TOKEN="<token from the OAuth2 registration>"
Soumettre une tâche
L’API du service web accepte les tâches d’impression, effectue le rendu d’étiquettes individuelles en PDF ou PNG et prend en charge l’impression directe. Les chemins exacts des points de terminaison et le schéma de la charge utile proviennent de la documentation de l’interface de service web — l’extrait ci-dessous montre la forme de l’appel, et ne remplace pas la référence :
import os
import requests
BASE = os.environ["LPSNG_BASE_URL"]
TOKEN = os.environ["LPSNG_TOKEN"]
job = {
# Payload keys are illustrative — use the schema from the
# web service interface documentation.
"label": "shipping-label",
"printer": "warehouse-zebra-01",
"data": {
"order_id": "A-10442",
"serial": "42", # the field script turns this into SN-000042
"printed_at": "", # left empty on purpose
},
}
resp = requests.post(
f"{BASE}/<print-endpoint-from-the-docs>",
headers={"Authorization": f"Bearer {TOKEN}"},
json=job,
timeout=30,
)
resp.raise_for_status()
print(resp.json()) # the response gives you the reference to poll
Remarquez ce que l’appelant ne fait pas : il ne formate pas le numéro de série, et il ne remplit pas printed_at. C’est désormais le rôle de l’étiquette.
Le cas intéressant : calculer une valeur
La transformation qui s’amortit le plus vite est une clé de contrôle, car une clé erronée signifie qu’un scanner rejette l’étiquette au poste d’emballage. Le script la calcule à partir de la valeur transmise par la tâche :
# Field: ean
# Compute the mod-10 check digit for a 12-digit payload.
digits = [int(c) for c in str(value) if c.isdigit()]
if len(digits) == 12:
checksum = (10 - (sum(digits[::2]) + 3 * sum(digits[1::2])) % 10) % 10
value = "".join(map(str, digits)) + str(checksum)
else:
# Defensive: don't render an invalid barcode silently.
value = "INVALID"
Comme le script modifie la valeur du champ avant le rendu du code-barres, le contenu du code-barres reflète le résultat calculé. Vous n’avez pas besoin d’une étape distincte de génération de code-barres.
La manière difficile, pour comparer
L’alternative consiste à calculer ces valeurs en amont : un préprocesseur qui lit vos données de commande, réécrit chaque champ, et n’appelle l’API qu’ensuite. Cela fonctionne, jusqu’à ce que le préprocesseur et le modèle d’étiquette ne soient plus d’accord — l’un complète à six chiffres, l’autre à huit — et que personne ne s’en aperçoive avant qu’une palette ne soit expédiée avec des numéros de série illisibles. Garder la logique à l’intérieur du modèle signifie qu’il existe exactement une définition de « correct » par champ.
Si vous devez exécuter la même logique d’étiquette ailleurs sans navigateur, le LPSNG Player est un moteur d’impression en ligne de commande autonome qui prend un paquet plus des données et produit un PDF, un PNG, un JSON, une impression directe ou une mise à jour ESL. Même étiquette, mêmes scripts, contexte d’exécution différent.
Surveiller et gérer les échecs en impression automatisée
Un pipeline automatisé qui échoue silencieusement est pire qu’un pipeline manuel, car personne ne regarde l’étiquette.
Surveillez la file d’attente. L’interface web dispose d’une file de tâches, et l’API du service web vous permet de vérifier l’état d’une tâche. Interrogez la référence renvoyée lors de la soumission, avec un backoff, et alertez lorsqu’une tâche reste trop longtemps dans le même état :
import time
def wait_for_job(session, base, job_ref, timeout=120, interval=5):
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
status = session.get(
f"{base}/<job-status-endpoint-from-the-docs>/{job_ref}",
timeout=15,
).json()
if status.get("state") in ("done", "failed"):
return status
time.sleep(interval)
raise TimeoutError(f"job {job_ref} did not finish in {timeout}s")
L’interface publiée documente la soumission de tâches, le rendu d’étiquettes individuelles, l’impression directe et l’état — elle ne décrit pas de webhooks, donc l’interrogation périodique est le modèle sur lequel s’appuyer. Si vous avez besoin de notifications push, considérez cela comme une lacune à combler de votre côté.
Échouez de manière défensive à l’intérieur du script. Décidez de ce qu’une mauvaise entrée doit produire avant que cela n’arrive. Un script qui affiche INVALID dans un champ code-barres vous rend service, comparé à un script qui lève une exception et fait échouer toute la tâche — ou qui lève une exception, se fait avaler, et imprime la valeur non formatée. Consultez la documentation de l’API de script de champ pour savoir comment la plateforme signale un bloc en échec, et écrivez vos scripts de sorte que le mode de défaillance soit celui que vous avez choisi.
Faites un essai à blanc avec le rendu. L’API du service web peut effectuer le rendu d’une étiquette individuelle en PDF ou PNG. Effectuez le rendu avant d’imprimer. C’est le test de fumée le moins coûteux dont vous disposez : fournissez au script une entrée connue, examinez la sortie, et seulement ensuite dirigez le pipeline vers l’imprimante.
Bonnes pratiques pour les scripts de champ Python
- Une transformation par script. Un bloc qui formate une date et recherche un nom de client et recalcule un total est un bloc que personne ne déboguera à 2 heures du matin.
- Soyez idempotent. Les réimpressions arrivent — une étiquette coincée, un carton rejeté, un opérateur qui appuie deux fois sur imprimer. Si
SN-000042repasse par le script, il doit ressortir sous la formeSN-000042, et nonSN-SN-000042. Vérifiez si la valeur a déjà la forme attendue avant de la transformer. - Versionnez les scripts en dehors de LPSNG. Conservez les définitions d’étiquettes et leurs blocs de script dans Git avec une courte note expliquant la raison d’être de chacun. La plateforme les stocke et les exécute ; elle ne remplace pas la revue de code.
- Ne codez jamais les données en dur. Pas de numéros de client fixes, pas de dates fixes, pas de logique de branchement propre à une imprimante. Tout doit provenir de la valeur du champ ou des données transmises dans la tâche d’impression.
- Restez léger. Évitez les opérations longues. Les scripts de champ s’exécutent dans le chemin d’impression, et un script lent est une étiquette lente.
- Testez avec de vraies anomalies. Chaînes vides, zéros initiaux, valeurs déjà formatées, valeurs beaucoup trop longues. C’est là que les scripts de champ cassent.
FAQ
Les scripts de champ Python peuvent-ils accéder à des API externes ou à des bases de données ?
L’API de script de champ est conçue pour accéder aux valeurs de champ et les modifier dans le contexte de l’étiquette. Pour des données externes, vous les transmettez généralement dans les données de la tâche d’impression. Consultez la documentation LPSNG pour les éventuelles limitations concernant les appels externes.
Quelle version de Python et quelles bibliothèques sont disponibles dans les scripts de champ ?
L’environnement Python exact est spécifié dans la documentation de l’API de script de champ LPSNG. Il est recommandé d’utiliser les fonctionnalités de la bibliothèque standard et de garder les scripts légers.
Comment les scripts de champ fonctionnent-ils avec les codes-barres ?
Les scripts peuvent modifier la valeur du champ avant le rendu du code-barres, ce qui vous permet de calculer des clés de contrôle, de formater des données ou d’appliquer des transformations qui affectent le contenu du code-barres.
Existe-t-il une limite au temps d’exécution des scripts ?
Les scripts de champ doivent être efficaces. Bien que les limites spécifiques ne soient pas détaillées dans les informations fournies, il est de bonne pratique d’éviter les opérations longues. Reportez-vous à la documentation LPSNG pour toute contrainte.
Conclusion
Le modèle est simple, et c’est pourquoi il tient : attachez la transformation au champ une fois, authentifiez-vous une fois, soumettez des tâches pour toujours. La modification manuelle disparaît, et la définition d’une étiquette correcte vit à exactement un endroit — le modèle — au lieu de dépendre de la personne qui se trouvait près de l’imprimante ce matin-là.
Commencez par un champ. Choisissez celui que votre équipe modifie le plus souvent, écrivez dix lignes de Python, effectuez le rendu d’un PDF et comparez-le à une étiquette de référence. Passez ensuite au suivant.
Next Generation Label Printing System est la plateforme gérée qui exécute ces scripts — le studio d’étiquettes, l’interface de service web OAuth2, la file de tâches et le Player — sans environnement Python local à maintenir. Vous pouvez voir le tableau complet sur lpsng.rsj.de.
Articles similaires
- Zebra Label Software Alternative: A Browser-Based Approach
- Building Order-Specific Labeling on Top of a Label Printing API
- How to Create Labels from Excel Data Files and Lookup Tables
