English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
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.
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.
#!/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>
Vous pouvez utiliser rescue Le bloc capture l'exception puis utilise retry La statement commence par l'exécution begin bloc.
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
#!/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.
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é.
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.
#!/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 :
#!/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"]
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é.
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
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
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.
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
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é.
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.
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
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.
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
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 :
class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason end end
Maintenant, voyons l'exemple suivant, qui utilise l'exception ci-dessus :
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.