Parfois, un projet qui semble simple sur le papier se transforme en véritable chasse aux bugs. Cette migration RoboTask vers Python pour la génération d'étiquettes d'expédition DPD en est l'exemple parfait : 4 versions successives ont été nécessaires pour résoudre un bug insidieux lié aux lecteurs Windows.

Voici le récit complet de cette migration, avec un focus particulier sur le problème du double backslash qui m'a fait comprendre pourquoi pathlib et les lecteurs Windows ne font pas toujours bon ménage.

Le Contexte : Automatiser DPD

Le Besoin Initial

Un client utilisait RoboTask (~200€/an) pour générer automatiquement des fichiers d'étiquettes DPD depuis sa base de données Cegid PMI. Le processus consistait à :

Le format DPD est particulier : largeur fixe de 56 colonnes, encodage ISO-8859-1, avec un en-tête $VERSION=110 et des données rigoureusement formatées.

~200€
Coût licence RoboTask/an
56
Colonnes SQL formatées
G:\
Lecteur réseau mappé
2 jours
Temps de migration total

Les Objectifs de Migration

Comme pour toute migration RoboTask vers Python, les objectifs étaient clairs :

Architecture Python : Simple et Modulaire

J'ai conçu une solution Python propre avec deux classes principales et plusieurs scripts utilitaires :

# Classes principales
DPDRecord       # Validation et formatage des données
DPDGenerator    # Orchestration et génération fichiers

# Scripts utilitaires
run_dpd_generation.bat    # Wrapper Windows
install_dpd.bat           # Installation 5 tâches planifiées
diagnostic.bat            # Diagnostic automatique
test_installation.py      # 7 tests de validation

Technologies utilisées :

Python 3.12 pyodbc SQL Server pathlib configparser

Fonctionnalités Clés

Les Défis Techniques : 4 Versions pour 1 Bug

Si j'avais su ce qui m'attendait avec le problème du double backslash, j'aurais peut-être utilisé os.path dès le début. Mais voici le parcours complet...

Version 1.0 → 1.1 : Logs Manquants

🔴 Problème

Le script s'exécutait via le Planificateur Windows mais aucun log n'était créé. Impossible de savoir ce qui se passait.

Cause : Le logging était initialisé trop tard dans le code. Si une erreur survenait pendant le chargement de la configuration, aucun log n'était écrit.

✅ Solution v1.1

# Initialiser le logging DÈS LE DÉBUT
def __init__(self):
    self._init_basic_logging()  # ← AVANT tout
    self.config = load_config()
    # ... reste du code

Améliorations :

  • Logs du wrapper batch (capture stdout/stderr)
  • Script de diagnostic automatique
  • Guide de dépannage (15+ pages)

Version 1.1 → 1.2 : Doublons d'Étiquettes

🔴 Problème

Les fichiers d'étiquettes étaient régénérés à chaque exécution, créant des doublons. Avec 5 tâches planifiées par jour pour les réessais, le problème s'amplifiait.

Cause : Le script vérifiait l'existence du fichier mais continuait quand même à traiter l'expédition et à ajouter des lignes.

✅ Solution v1.2

# Vérifier AVANT le traitement
for expedition in expeditions:
    archive_file = output_dir / f"{expedition_id}.txt"
    
    if archive_file.exists():
        logging.info(f"DEJA TRAITEE - Skip {expedition_id}")
        skipped_count += 1
        continue  # ← Skip complet
    
    # Traitement uniquement si fichier inexistant
    process_expedition(expedition)

Impact : Support multi-exécutions sans doublons + statistiques précises (compteur de skipped)

Versions 1.3 → 1.3.4 : Le Cauchemar du Double Backslash

Et là commence le vrai calvaire. Un bug qui m'a pris 4 itérations et plusieurs heures de débogage pour comprendre que pathlib et les lecteurs Windows ont un problème fondamental.

Itération 1 : Vérification d'Existence (v1.3.1)

🔴 Symptôme

[WinError 3] Le chemin d'accès spécifié est introuvable: 'G:\\'

Le script plantait avec un double backslash mystérieux.

Analyse : En testant Path("G:").exists(), Python ajoutait automatiquement un backslash, créant "G:\\" qui est invalide pour Windows.

# Ce qui se passait
drive_path = Path("G:")      # Semble OK
drive_path.exists()          # Devient "G:\\" en interne
# → WinError 3

✅ Tentative de Solution v1.3.1

# Construire explicitement le chemin
drive_path = directory.drive + '\\'  # "G:\"
if not Path(drive_path).exists():
    raise FileNotFoundError(f"Lecteur {drive_path} inaccessible")

Mais ce n'était pas suffisant...

Itération 2 : Faux Positif (v1.3.3)

🔴 Nouveau Problème

Le script détectait G:\ comme inaccessible alors qu'il était accessible. La vérification avec Path.exists() échouait dans certains contextes (compte SYSTEM, tâches planifiées).

✅ Solution v1.3.3

Suppression de la vérification préalable. L'erreur sera détectée lors de l'utilisation réelle.

# Plus de vérification préalable
# L'erreur sera attrapée au moment de l'écriture
try:
    file_path.write_text(content)
except Exception as e:
    logging.error(f"Erreur écriture : {e}")

Itération 3 : Création de Dossiers (v1.3.4) - FINAL 🎯

🔴 Le Bug Persiste !

[WinError 3] Le chemin d'accès spécifié est introuvable: 'G:\\'

Même erreur, mais cette fois lors de la création des dossiers. Path.mkdir(parents=True) essayait de créer la racine G:\ et échouait avec le double backslash.

Analyse Approfondie :

# Ce qui se passait avec pathlib
directory = Path("G:/DPD/Archive")
directory.mkdir(parents=True)  # Essaie de créer toute la hiérarchie

# Étapes internes de pathlib :
# 1. Décompose : ['G:', 'DPD', 'Archive']
# 2. Essaie de créer G:
# 3. Path("G:") devient "G:\\" en interne
# 4. → WinError 3

✅ Solution Définitive v1.3.4

# Remplacer Path.mkdir par os.makedirs
import os

# Au lieu de
directory.mkdir(parents=True, exist_ok=True)

# Utiliser
os.makedirs(str(directory), exist_ok=True)

Pourquoi ça fonctionne :

  • os.makedirs() utilise les API Windows natives
  • ✅ Pas de conversion Path qui introduit le double backslash
  • ✅ Gère parfaitement les lecteurs Windows (G:, H:, etc.)
  • exist_ok=True évite les erreurs si dossier existe

🎓 Leçon Apprise : pathlib vs os.path sur Windows

Sur Windows avec lecteurs mappés :

Opération ❌ pathlib (problèmes) ✅ os.path (OK)
Vérifier existence Path("G:").exists()
→ Double backslash
os.path.exists("G:")
→ Fonctionne
Créer dossiers Path.mkdir(parents=True)
→ Double backslash
os.makedirs()
→ Fonctionne
Chemins internes Conversion automatique problématique Respecte le format Windows natif

Recommandation : Sur Windows, avec des lecteurs mappés, privilégiez os.path et os.makedirs plutôt que pathlib.

Timeline des Versions

v1.0 - Migration Initiale

Migration fonctionnelle de base. Problème : pas de logs en cas d'erreur.

v1.1 - Logs Corrigés

Logging initialisé dès le début + wrapper batch avec logs.

v1.2 - Anti-Doublons

Skip complet des expéditions déjà traitées. Support multi-exécutions.

v1.3.1 - Premier Bug Backslash

Construction explicite des chemins lecteurs. Erreur persiste.

v1.3.3 - Suppression Vérification

Retrait de la vérification préalable. Bug se manifeste ailleurs.

v1.3.4 - Solution Définitive ✅

Remplacement de Path.mkdir par os.makedirs. Bug résolu !

Résultats : Mission Accomplie

Métriques Finales

500+
Lignes de code Python
100%
Conformité fonctionnelle
8
Versions successives
100+
Pages de documentation

Améliorations vs RoboTask

Critère RoboTask Python
Coût ~200€/an 0€ (gratuit)
Logs Basiques Détaillés, horodatés, par jour
Doublons Possible si multi-run Impossible (skip automatique)
Versionning Fichiers binaires Git (8 versions trackées)
Maintenance Interface graphique Code lisible et documenté
Tests Manuels 7 tests automatisés
Diagnostic Difficile Script automatique
Documentation Minimale 100+ pages (9 guides)

Documentation Produite

Un des points forts de cette migration : une documentation exhaustive pour ne plus jamais perdre de temps sur les mêmes problèmes.

Total : 9 documents techniques, 100+ pages

Besoin de Migrer une Automatisation RoboTask ?

Je développe des solutions Python pour remplacer RoboTask et autres outils propriétaires. Migration, debugging Windows, ou création from scratch — discutons de votre projet !

Parlons de votre automatisation

Leçons Apprises

1. pathlib et Windows : Une Relation Compliquée

pathlib est excellent sur Linux et macOS, mais sur Windows avec des lecteurs mappés, privilégiez os.path et os.makedirs. Le double backslash n'est pas un bug Python, c'est une incompatibilité fondamentale entre la façon dont pathlib gère les chemins et les attentes de l'API Windows.

2. Tester dans le Contexte Réel Dès le Début

J'aurais pu éviter 3 versions intermédiaires en testant avec un lecteur mappé dès le début. Les tests unitaires sur C:\ ne révèlent pas les problèmes spécifiques aux lecteurs réseau (G:, H:, etc.).

3. Logging : La Clé du Débogage

Sans logs détaillés, je serais encore en train de chercher pourquoi le script ne fonctionne pas. Investissez dans un système de logging robuste dès le début : logs horodatés, niveaux de gravité, rotation automatique.

4. Documentation = Investissement Rentable

Les 100+ pages de documentation semblent excessives, mais elles éviteront des heures de débogage futur. Chaque bug résolu et documenté devient une référence pour la suite.

5. Versionning Rigoureux

Utiliser Git avec un CHANGELOG.md détaillé a permis de tracker précisément l'évolution du projet. Chaque version corrige un problème spécifique et peut être comparée.

Recommandations pour Projets Similaires

Avant de Commencer

Pendant le Développement

Après Déploiement

Conclusion

Cette migration RoboTask → Python fut plus complexe que prévu à cause du bug du double backslash, mais le résultat final est production-ready avec :

La leçon principale ? Sur Windows, quand vous travaillez avec des lecteurs mappés, os.path et os.makedirs sont vos amis. pathlib est excellent, mais pas pour ce cas d'usage spécifique.

ROI : Immédiat (économie licence + maintenabilité)
Temps : 2 jours (incluant 4 itérations bug)
Statut : ✅ Production-ready avec zéro erreur depuis le déploiement

JC

Jean-Charles - SysLibre

Développeur freelance spécialisé en Python, automatisation et intégration de systèmes. J'aide les entreprises à moderniser leurs processus et à résoudre des bugs Windows particulièrement retors. Basé à Joué-lès-Tours, intervenant partout en France.