Ruby Exceptions

Les exceptions et l'exécution sont toujours liées. Si vous ouvrez un fichier qui n'existe pas et ne gérez pas correctement cette situation, votre programme est considéré comme de mauvaise qualité.

Si une exception se produit, le programme s'arrête. Les exceptions servent à gérer divers types d'erreurs pouvant survenir pendant l'exécution d'un programme, afin que des mesures appropriées puissent être prises sans laisser le programme s'arrêter complètement.

Ruby fournit un mécanisme parfait pour gérer les exceptions. Nous pouvonsbegin/endattacher dans un bloc du code susceptible de lever une exception, et utiliser la clauserescuepour indiquer à Ruby exactement quels types d'exceptions gérer.

Syntaxe

begin #begin raise.. #lever une exception rescue [ExceptionType = StandardException] #Capture les exceptions du type spécifié, la valeur par défaut est StandardError $! #Représente les informations sur l'exception $@ #Représente l'emplacement du code où l'exception s'est produite else #Exceptions restantes .. ensure #Que l'exception se produise ou non, entrez dans ce bloc de code end #end

debeginàrescueTout ce qui se trouve à l'intérieur est protégé. Si une exception se produit pendant l'exécution du bloc, le contrôle est passé àrescueetendle bloc entre les deux.

Pourbeginchaquerescueclause dans le bloc, Ruby compare l'exception levée avec chaque paramètre tour à tour. Si l'exception nommée dans une clause rescue est du même type que l'exception actuellement levée, ou est une classe parente de cette exception, alors la correspondance réussit.

Si l'exception ne correspond pas à tous les types d'erreur spécifiés, nous pouvons, après toutes les clausesrescue, utiliser une clauseelse.

Exemples

#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "Fichier ouvert avec succès" end rescue file = STDIN end print file, "==", STDIN, "\n"

L'exemple ci-dessus affiche le résultat. Vous pouvez voir,STDINa remplacéfile, parce quel'ouverturea échoué.

#<IO:0xb7d16f84>==#<IO:0xb7d16f84>

Utilisation deretryinstruction

Vous pouvez utiliserrescueun bloc pour intercepter des exceptions, puis utiliserretryinstruction pour exécuter depuis le débutbeginbloc.

Syntaxe

begin #L'exception levée par ce code sera interceptée par la clause rescue suivante rescue #Ce bloc interceptera tous les types d'exceptions retry #Cela déplacera le contrôle au début de begin end

Exemples

#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "Fichier ouvert avec succès" end rescue fname = "existant_file" retry end

Ce qui suit est le déroulement du traitement :

  • Une exception se produit lors de l'ouverture.
  • Saut vers rescue. fname est réaffecté.
  • Saut au début de begin via retry.
  • Cette fois, le fichier s'ouvre avec succès.
  • Continuer avec le processus de base.

Remarque :Si le fichier renommé n'existe pas, cet exemple de code essaiera à l'infini. Donc, lors de la gestion des exceptions, utilisez avec prudenceretry。

En utilisantraiseInstruction

Vous pouvez utiliserraiseinstruction pour lever une exception. La méthode suivante lève une exception lorsqu'elle est appelée. Son deuxième message sera affiché.

Syntaxe

raiseouraise "Message d'erreur"ouraise ExceptionType, "Message d'erreur"ouraise ExceptionType, "Message d'erreur" condition

La première forme se contente de relancer l'exception courante (ou lève une RuntimeError s'il n'y a pas d'exception courante). Elle est utilisée dans les gestionnaires d'exceptions qui doivent expliquer l'exception avant de la transmettre.

La deuxième forme crée une nouvelle exceptionRuntimeError, en définissant son message sur la chaîne donnée. L'exception est ensuite propagée dans la pile d'appels.

La troisième forme crée une exception en utilisant le premier paramètre, puis définit le message associé sur le deuxième paramètre.

La quatrième forme est semblable à la troisième forme, et vous pouvez ajouter d'autres instructions conditionnelles (telles queunless) pour lever l'exception.

Exemples

#!/usr/bin/ruby begin puts 'Je suis avant le raise.' raise 'Une erreur s'est produite.' puts 'Je suis après le raise.' rescue puts 'Je suis rattrapé.' end puts 'Je suis après le bloc begin.'

L'exemple ci-dessus produit :

I am before the raise.  
I am rescued.  
I am after the begin block.  

Une autre démonstrationraiseexemple d'utilisation :

Exemples

#!/usr/bin/ruby begin raise 'Une exception de test.' rescue Exception => e puts e.message puts e.backtrace.inspect end

L'exemple ci-dessus produit :

A test exception.
["main.rb:4"]

Utilisation de l'instructionensureStatement

Parfois, qu'une exception soit levée ou non, vous devez vous assurer qu'un certain traitement est terminé lorsque le bloc de code se termine. Par exemple, vous avez peut-être ouvert un fichier à l'entrée, et lorsque vous quittez le bloc, vous devez vous assurer que le fichier est fermé.

ensureLa clause ensure fait exactement cela. ensure est placée après la dernière clause rescue et contient un bloc de code qui est toujours exécuté lorsque le bloc se termine. Peu importe que le bloc se termine normalement, qu'il déclenche et gère une exception, ou qu'il se termine en raison d'une exception non interceptée,ensurele bloc s'exécutera toujours.

Syntaxe

begin #.. traitement #.. lever une exception rescue #.. gérer l'erreur ensure #.. enfin assurer l'exécution #.. ceci s'exécutera toujours end

Exemples

begin raise 'Une exception de test.' rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "Assurer l'exécution" end

L'exemple ci-dessus produit :

A test exception.
["main.rb:4"]
Ensuring execution

Utilisation de l'instructionelseStatement

Si une clauseelseest fournie, elle est généralement placée après la clauserescue, avant toute clauseensureavant.

elseLe corps de la clause n'est exécuté que lorsque le corps principal du code ne lève pas d'exception.

Syntaxe

begin #.. traitement #.. lever une exception rescue #.. traiter l'erreur else #.. exécuter si aucune exception ensure #.. enfin assurer l'exécution #.. ceci s'exécutera toujours end

Exemples

begin #raise 'Une exception de test.' puts "Je ne lève pas d'exception" rescue Exception => e puts e.message puts e.backtrace.inspect else puts "Félicitations-- aucune erreur !" ensure puts "Assurer l'exécution" end

L'exemple ci-dessus produit :

I'm not raising exception
Congratulations-- no errors!
Ensuring execution

En utilisant la variable $!, vous pouvez capturer le message d'erreur levé.

Catch et Throw

Le mécanisme d'exception de raise et rescue peut abandonner l'exécution lorsqu'une erreur se produit. Parfois, vous devez sortir de certaines structures profondément imbriquées pendant le traitement normal. C'est là que catch et throw sont utiles.

catchdéfinit un bloc qui utilise le nom donné (qui peut être un Symbol ou une String) comme étiquette. Le bloc s'exécute normalement jusqu'à ce qu'il rencontre un throw.

Syntaxe

throw :lablename #.. ceci ne sera pas exécuté catch :lablename do #.. catch qui sera exécuté après avoir rencontré un throw endorthrow :lablename condition #.. ceci ne sera pas exécuté catch :lablename do #.. catch qui sera exécuté après avoir rencontré un throw end

Exemples

Dans l'exemple suivant, si l'utilisateur tape '!' en réponse à n'importe quelle invite, un throw est utilisé pour terminer l'interaction avec l'utilisateur.

Exemples

def promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res end catch :quitRequested do name = promptAndGet("Nom : ") age = promptAndGet("Âge : ") sex = promptAndGet("Sexe : ") # .. #Traitement des informations end promptAndGet("Nom :")

Le programme ci-dessus nécessite une interaction humaine ; vous pouvez l'essayer sur votre ordinateur. L'exemple ci-dessus produit :

Name: Ruby on Rails
Age: 3
Sex: !
Name:Just Ruby

Classe Exception

Les classes et modules standard de Ruby lèvent des exceptions. Toutes les classes d'exception forment une hiérarchie, avec la classe Exception au sommet. Le niveau inférieur se compose de sept types différents :

  • Interrompre
  • NoMemoryError
  • SignalException
  • ScriptError
  • StandardError
  • SystemExit

Fatal est une autre exception de ce niveau, mais l'interpréteur Ruby ne l'utilise qu'en interne.

ScriptError et StandardError ont tous deux des sous-classes, mais nous n'avons pas besoin de comprendre ces détails ici. Le plus important est de créer nos propres classes d'exception, qui doivent être des sous-classes de la classe Exception ou de ses descendants.

Regardons un exemple :

Exemples

class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason end end

Maintenant, regardez l'exemple suivant, qui utilisera l'exception ci-dessus :

Exemples

File.open(path, "w") do |file| begin #Écrire des données ... rescue #Une erreur s'est produite raise FileSaveError.new($!) end end

Ici, la ligne la plus importante est raiseFileSaveError.new($!). Nous appelons raise pour signaler qu'une exception s'est produite, en passant une nouvelle instance de FileSaveError parce que l'exception spécifique a causé l'échec de l'écriture des données.

Autres extensions