Communauté Eggdrop
Try/Catch: comment gérer ses erreurs facilement. - Version imprimable

+- Communauté Eggdrop (https://forum.eggdrop.fr)
+-- Forum : Eggdrop et TCL (https://forum.eggdrop.fr/forumdisplay.php?fid=8)
+--- Forum : Scripts TCL (https://forum.eggdrop.fr/forumdisplay.php?fid=4)
+--- Sujet : Try/Catch: comment gérer ses erreurs facilement. (/showthread.php?tid=236)



Try/Catch: comment gérer ses erreurs facilement. - Merwin - 14/06/2008

En Tcl il n'est pas toujours très intuitif et simple de gérer les erreurs, j'ai donc programmé une procédure pour faire cela.

Ce code ne fonctionne qu'avec Tcl 8.5 ! Pour Tcl 8.4 vous pouvez utiliser la librairies mkGeneric (http://mkextensions.sf.net) !

TCL
# try Script ?catch Pattern CatchScript ...? ?catch DefaultCatchScript? ?finally FinallyScript?
#
#   Cette fonction a pour but d'intercepter les erreurs Tcl simplement, lorsque
#   vous utilisez try, le Script est exécuté, s'il génère une erreur il cherche un
#   catchScript correspondant au type d'erreur spécifié dans Pattern en se
#   basant sur une recherche avec des jokers comme string match.
#
#   S'il n'en trouve pas il exécute le DefaultCatchScript, s'il n'est pas
#   spécifié il ignore l'erreur. Puis à la fin il exécute le FinallyScript dans
#   tous les cas (si votre script génère une erreur).
#
#   Si jamais votre CatchScript génère une erreur elle est propagée, si votre
#   FinallyScript génère une erreur elle est propagée en prioritée.
#
#   L'erreur générée par votre Script est stockée dans $::errorMsg, vous possédez
#   donc trois variables pour afficher l'erreur: $::errorMsg, $::errorInfo et
#   $::errorCode.
 
proc try {script args} {
 
    # On parse $args pour sortir un tableau des pattern de catch, $arrayCatchs.
    # Chaque entrée du tableau est un pattern sauf les valeurs _default et
    # _finally qui sont réservées.
 
    set arrayCatchs(_default) [list]
    set arrayCatchs(_finally) [list]
    set foundPattern 0
    set catchErr 0
 
    for {set i 0} {$i <= [llength $args]} {incr i} {
 
        lassign [lrange $args $i [expr {$i + 2}]] current pattern code
 
        if {$current eq "catch"} {
            if { ($code eq "catch") || ($code eq "") || ($code eq "finally")} {
                set arrayCatchs(_default) $pattern
            } else {
                set arrayCatchs($pattern) $code
            }
        }
 
        if {$current eq "finally"} {
            set arrayCatchs(_finally) $pattern
        }
    }

    # On exécute le script et on voit s'il retourne une erreur.
    # Si c'est le cas alors on doit regarder si on a un pattern qui correspond
    # au code d'erreur retourné et mettre le script à éxécuté dans $catchScript.
 
    switch -- [catch [list uplevel 1 $script] scriptRes scriptOpt] {
        1 {
            foreach pattern [array names arrayCatchs] {
                if { [string match $pattern [dict get $scriptOpt -errorcode]] } {
                    set catchScript $arrayCatchs($pattern)
                    set foundPattern 1
                }
            }
 
            if {!$foundPattern} {
                set catchScript $arrayCatchs(_default)
            }
 
            set ::errorMsg $scriptRes
        }
        2 {return -code return}
        3 {return -code break}
        4 {return -code continue}
        0 {return -code ok $scriptRes}
    }
    
    # A partir de maintenant, notre script a retourné une erreur, et on a le code
    # a éxécuté en cas d'erreur dans $catchScript. On doit donc éxécuter notre
    # catchScript, s'il retourne une erreur on devra la propager, de même
    # pour continue et break.    
 
    if { [set catchStatus [catch [list uplevel 1 $catchScript] catchRes catchOpt]] } {
        if { $catchStatus eq 1 } {set catchErr 1}
    }
 
    if { [catch [uplevel 1 $arrayCatchs(_finally)] finallyRes finallyOpt] } {
        # En cas d'erreur dans le catch on exécute le finally AVANT de
        # propager l'erreur du catch car si il y a une erreur dans le
        # le finally on doit la propager en prioritée.
        return -options $finallyOpt
    }
 
    if {$catchErr} {
        return -options $catchOpt
    } else {
        switch -- $catchStatus {
            0 {return -code ok $catchRes}
            2 {return -code return}
            3 {return -code break}
            4 {return -code continue}
        }
    }
}

# throw ?errorCode? ?errorMsg? ?errorInfo?
#
# Cette commande est identique à error sauf que vous ne spécifiez pas
# les arguments dans le même ordre. Elle est utile utilisée en parralèle avec
# try car vous pouvez spécifiez un code d'erreur spécifique pour try.
# 
 
proc throw {errorCode args} {
    lassign $args errorMsg errorInfo
    return -code error -errorinfo $errorInfo -errorcode $errorCode $errorMsg
}



Exemple:

TCL
try {
   set fileID [open monfichier.txt]
   puts $fileID "LOL"
   close $fileID
} catch {
   puts "Erreur lors de l'écriture dans le fichier: $::errorMsg"
} finally {
   puts "Ce code sera exécuté même si le code dans catch est erroné!"
}



Pour les utilisateurs un peu plus poussé vous pouvez spécifiez des codes d'erreur après le catch comme ceci:

TCL
try {
   expr {100/0}
} catch "ARITH*" {
   puts "Erreur mathématique: $::errorCode ($::errorMsg)"
} catch {
   puts "Autre erreur: $::errorCode ($::errorMsg)"
}



Vous pouvez aussi générez vos propres codes d'erreur avec throw Smile


RE: Try/Catch: comment gérer ses erreurs facilement. - CrazyCat - 15/06/2008

Wow merci bien, très pratique, surtout que tcl8.5 est passé en version stable de debian (et donc des autres distributions je présume).

Il serait p-e intéressant de mettre ça dans alltools.tcl (en fait, je me crée un espèce de alltools avec les fonctions pratiques et génériques)


RE: Try/Catch: comment gérer ses erreurs facilement. - Merwin - 15/06/2008

Fais donc si tu veux, mes codes sont libres Wink


RE: Try/Catch: comment gérer ses erreurs facilement. - Mareo - 04/06/2010

Il me semble que la gestion des exception viendra nativement avec tcl 8.6


RE: Try/Catch: comment gérer ses erreurs facilement. - djkenny - 28/02/2011

Citation :Posté par aliassangelius - 04-06-2010 20:00
j'ai ça moi sinon

t en a pas mare de pomper les codes des autres?
ca viens de mon tcl-bot !!!!


RE: Try/Catch: comment gérer ses erreurs facilement. - BeussAy - 02/03/2011

http://www.eggdrop.fr/board/Propriete-des-scripts-t-895.html
PS: Perso je rejoins ce qui est dit dans le post.

Smile