English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Exceptions Ruby

Les exceptions et l'exécution sont toujours liées. Si vous ouvrez un fichier inexistant et que vous ne traitez 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 sont utilisées pour traiter divers types d'erreurs qui peuvent survenir pendant l'exécution du programme, il est donc nécessaire de prendre des mesures appropriées pour éviter que le programme ne cesse complètement de fonctionner.

Ruby offre un mécanisme parfait pour gérer les exceptions. Nous pouvons begin/end Ajoutez le code susceptible de générer des exceptions dans le bloc, et utilisez rescue la clause indique au Ruby le type d'exception à traiter parfaitement.

Syntaxe

begin # commence
 
 raise ... # lève une exception
 
rescue [ExceptionType = StandardException] # attrape l'exception spécifiée par défaut StandardException
 $! # indique les informations sur l'exception
 $@ # indique la position du code où l'exception s'est produite
else # les autres exceptions
 ...
ensure # peu importe s'il y a une exception ou non, entrez dans ce bloc de code
 
end # fin

à begin de rescue à rescue tout ce qui est protégé. Si une exception se produit pendant l'exécution du bloc de code, le contrôle est transféré à end et

entre begin Chaque rescue clauses, Ruby compare l'exception lancée avec chaque paramètre en alternance. Si l'exception nommée dans la clause rescue correspond au type d'exception actuelle ou à une classe parente de cette exception, une correspondance réussie a lieu.

Si l'exception ne correspond pas à tous les types d'erreurs spécifiés, nous pouvons dans toutes les rescue après une clause sinon clause.

Exemple en ligne

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
      file = STDIN
end
print file, "==", STDIN, "\n"

Le résultat de l'exécution de l'exemple ci-dessus est. Vous pouvez voir que,STDIN remplace file parce queOuvriréchoue.

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

utiliser retry l'instruction

Vous pouvez utiliser rescue Le bloc capture l'exception puis utilise retry La statement commence par l'exécution begin bloc.

Syntaxe

begin
    # Les exceptions lancées par ce code seront capturées par la clause rescue suivante
rescue
    # Ce bloc capture tous types d'exceptions
    retry # Cela déplace le contrôle au début de begin
end

Exemple en ligne

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
   fname = "existant_file"
   retry
end

Voici le flux de traitement :

  • Exception lors de l'ouverture.

  • Sauter à rescue.fname est assignée de nouveau.

  • Avec retry, sautez au début de begin.

  • Cette fois, le fichier a été ouvert avec succès.

  • Continuez avec le processus de base.

Attention :Si le fichier renommé n'existe pas, le code d'exemple suivant essaiera à l'infini. Donc, soyez prudent lors de la gestion des exceptions. retry.

utiliser raise l'instruction

Vous pouvez utiliser raise La statement lance une exception. La méthode suivante lance une exception lors de l'appel. Son deuxième message sera affiché.

Syntaxe

raise 
 
ou
 
raise "Error Message" 
 
ou
 
raise ExceptionType, "Error Message"
 
ou
 
raise ExceptionType, "Error Message" condition

La première forme réétend simplement l'exception actuelle (sinon, une RuntimeError est lancée). Cela est utilisé dans le gestionnaire d'exceptions qui nécessite une explication de l'exception avant l'envoi.

La deuxième forme crée une nouvelle RuntimeError Exception, configurez son message avec la chaîne fournie. Cette exception est ensuite lancée dans la pile d'appel.

La troisième forme utilise le premier paramètre pour créer une exception, puis configure le message associé en tant que second paramètre.

La quatrième forme est similaire à la troisième, vous pouvez ajouter n'importe quelles conditions supplémentaires (par exemple sauf si) pour lever une exception.

Exemple en ligne

#!/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 sauvé.'  
end  
puts 'Je suis après le bloc begin.'

Le résultat de la sortie d'exécution de l'exemple ci-dessus est :

Je suis avant le raise.  
Je suis sauvé.  
Je suis après le bloc begin.

Un autre exemple raise Exemple d'utilisation :

Exemple en ligne

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

Le résultat de la sortie d'exécution de l'exemple ci-dessus est :

Une 'exception de test.'
["main.rb:"4"]

utiliser assurer l'instruction

Parfois, vous devez garantir que certaines opérations soient effectuées à la fin du bloc de code, que ce soit ou non une exception est levée. Par exemple, vous pourriez ouvrir un fichier au début, et vous devez vous assurer de fermer le fichier lorsque vous sortez du bloc.

assurer Ce que fait la clause est ceci. ensure est placé après la dernière clause rescue et contient un bloc de code qui est toujours exécuté à la fin du bloc. Il n'a aucune relation avec le fait que le bloc sorte normalement, lève et traite une exception, ou se termine par une exception non capturée,assurer Le bloc est toujours exécuté.

Syntaxe

begin 
   #.. Processus
   #.. Lèvez une exception
rescue 
   #.. Traitez les erreurs 
assurer 
   #.. Assurez-vous que l'exécution est terminée
   #.. Cela s'exécute toujours
end

Exemple en ligne

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

Le résultat de la sortie d'exécution de l'exemple ci-dessus est :

Une 'exception de test.'
["main.rb:"4"]
Assurer l'exécution

utiliser sinon l'instruction

si fourni sinon une clause, qui est généralement placée rescue Après la clause, n'importe assurer Précédemment.

sinon Le corps de la clause n'est exécuté que si le corps du code ne lève pas d'exception.

Syntaxe

begin 
   #.. Processus 
   #.. Lèvez une exception
rescue 
   #.. Traitez les erreurs
sinon
   #.. Si il n'y a pas d'exception, exécutez
assurer 
   #.. Assurez-vous que l'exécution est terminée
   #.. Cela s'exécute toujours
end

Exemple en ligne

begin
 # Lève une 'exception de test.'
 puts "Je ne lève pas d'exception"
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
sinon
   puts "Félicitations"-- sans erreurs !"
assurer
  puts "Assurer l'exécution"
end

Le résultat de la sortie d'exécution de l'exemple ci-dessus est :

Je ne lève pas d'exception
Félicitations-- sans erreurs !
Assurer l'exécution

L'utilisation de la variable $! permet de capturer le message d'erreur lancé.

Catch et Throw

Les mécanismes d'exception raise et rescue peuvent abandonner l'exécution lors d'une erreur, il peut parfois être nécessaire de sauter des structures imbriquées profondes lors du traitement normal. C'est à ce moment-là que catch et throw deviennent utiles.

catch Définit un bloc utilisant un 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
#.. Ce n'ira pas être exécuté
catch :lablename do
#.. match après un throw qui sera exécuté
end
 
ou
 
throw :lablename condition
#.. Ce n'ira pas être exécuté
catch :lablename do
#.. match après un throw qui sera exécuté
end

Exemple en ligne

Dans l'exemple suivant, si l'utilisateur tape '!' en réponse à n'importe quel prompt, utilisez un throw pour terminer l'interaction avec l'utilisateur.

Exemple en ligne

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:  ")
   # ..
   # traiter les informations
end
promptAndGet("Nom:")

Le programme suivant nécessite une interaction humaine, vous pouvez l'essayer sur votre ordinateur. Le résultat de l'exécution de l'exemple suivant est :

Nom: Ruby on Rails
Âge: 3
Sexe: !
Nom:Just Ruby

Classe Exception

Les classes et modules standards de Ruby lancent des exceptions. Toutes les classes d'exceptions constituent une hiérarchie, y compris la classe Exception en haut. Le niveau suivant est composé de sept types différents :

  • Interrupt

  • NoMemoryError

  • SignalException

  • ScriptError

  • StandardError

  • SystemExit

Fatal est une autre exception dans cette couche, mais l'interpréteur Ruby l'utilise uniquement en interne.

ScriptError et StandardError ont certains sous-classements, mais ici nous n'avons pas besoin de comprendre ces détails. Ce qui est le plus important est de créer nos propres classes d'exceptions, qui doivent être des sous-classes de Exception ou de ses sous-classes.

Voyons un exemple :

Exemple en ligne

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

Maintenant, voyons l'exemple suivant, qui utilise l'exception ci-dessus :

Exemple en ligne

File.open(path, "w") do |file|
begin
    # Écrire des données ...
rescue
    # Erreur survenue
    raise FileSaveError.new($!)
end
end

Ligne la plus importante ici est raise FileSaveError.new($!)Nous utilisons raise pour indiquer que l'exception s'est produite, et nous la transmettons à un nouvel exemple de FileSaveError en raison de l'échec de l'écriture des données en raison de l'exception spécifique.