Ruby Ausnahmen

Ausnahmen und Ausführung sind immer miteinander verbunden. Wenn Sie eine Datei öffnen, die nicht existiert, und diese Situation nicht ordnungsgemäß behandeln, gilt Ihr Programm als minderwertig.

Wenn eine Ausnahme auftritt, wird das Programm beendet. Ausnahmen werden verwendet, um verschiedene Fehlertypen zu behandeln, die während der Programmausführung auftreten können, sodass geeignete Maßnahmen ergriffen werden können, ohne das Programm vollständig anzuhalten.

Ruby bietet einen perfekten Mechanismus zur Behandlung von Ausnahmen. Wir könnenbegin/endCode, der eine Ausnahme auslösen kann, in einen Block einfügen und dierescue-Klausel verwenden, um Ruby genau mitzuteilen, welche Ausnahmetypen behandelt werden sollen.

Syntax

begin #begin raise.. #eine Ausnahme auslösen rescue [ExceptionType = StandardException] #Fängt Ausnahmen des angegebenen Typs ab, Standard ist StandardError $! #Repräsentiert Ausnahmeinformationen $@ #Repräsentiert die Codestelle, an der die Ausnahme aufgetreten ist else #Verbleibende Ausnahmen .. ensure #Unabhängig davon, ob eine Ausnahme vorliegt, wird dieser Codeblock ausgeführt end #end

vonbeginbisrescueAlles darin ist geschützt. Wenn während der Ausführung des Blocks eine Ausnahme auftritt, wird die Kontrolle anrescue übergebenundendden Block dazwischen.

Fürbeginjedes im Blockrescue-Klausel vergleicht Ruby die ausgelöste Ausnahme der Reihe nach mit jedem Parameter. Wenn die in einer rescue-Klausel genannte Ausnahme denselben Typ wie die aktuell ausgelöste Ausnahme hat oder eine Elternklasse dieser Ausnahme ist, dann ist die Übereinstimmung erfolgreich.

Wenn die Ausnahme nicht mit allen angegebenen Fehlertypen übereinstimmt, können wir nach allen denrescue-Klauseln eineelse-Klausel verwenden.

Beispiele

#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "Datei erfolgreich geöffnet" end rescue file = STDIN end print file, "==", STDIN, "\n"

Das obige Beispiel gibt das Ergebnis aus. Sie können sehen,STDINersetztfile, weil dasÖffnenfehlgeschlagen.

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

Verwendung derretryAnweisung

Sie könnenrescueeinen Block verwenden, um Ausnahmen abzufangen, dann verwenden SieretryAnweisung, um von Anfang an auszuführenbeginBlock.

Syntax

begin #Die von diesem Code ausgelöste Ausnahme wird von der folgenden rescue-Klausel abgefangen rescue #Dieser Block fängt alle Arten von Ausnahmen ab retry #Dies bewegt die Kontrolle an den Anfang von begin end

Beispiele

#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "Datei erfolgreich geöffnet" end rescue fname = "existant_file" retry end

Der folgende Ablauf beschreibt die Verarbeitung:

  • Beim Öffnen tritt eine Ausnahme auf.
  • Sprung zu rescue. fname wird neu zugewiesen.
  • Sprung zum Anfang von begin über retry.
  • Dieses Mal öffnet sich die Datei erfolgreich.
  • Mit dem grundlegenden Ablauf fortfahren.

Hinweis:Wenn die umbenannte Datei nicht existiert, versucht dieser Beispielcode unendlich oft. Seien Sie daher beim Behandeln von Ausnahmen vorsichtig mitretry。

Verwendung derraiseAnweisung

Sie können dieraiseAnweisung verwenden, um eine Ausnahme auszulösen. Die folgende Methode löst beim Aufruf eine Ausnahme aus. Ihre zweite Meldung wird ausgegeben.

Syntax

raiseoderraise "Fehlermeldung"oderraise ExceptionType, "Fehlermeldung"oderraise ExceptionType, "Fehlermeldung" Bedingung

Die erste Form löst einfach die aktuelle Ausnahme erneut aus (oder löst einen RuntimeError aus, wenn keine aktuelle Ausnahme vorhanden ist). Sie wird in Ausnahmebehandlern verwendet, die die Ausnahme erklären müssen, bevor sie weitergegeben wird.

Die zweite Form erstellt eine neueRuntimeError-Ausnahme und setzt ihre Meldung auf die angegebene Zeichenkette. Die Ausnahme wird dann an den Aufrufstapel geworfen.

Die dritte Form erstellt eine Ausnahme unter Verwendung des ersten Parameters und legt dann die zugehörige Meldung auf den zweiten Parameter fest.

Die vierte Form ähnelt der dritten Form, und Sie können beliebige zusätzliche bedingte Anweisungen (wieunless) hinzufügen, um die Ausnahme auszulösen.

Beispiele

#!/usr/bin/ruby begin puts 'Ich bin vor dem raise.' raise 'Ein Fehler ist aufgetreten.' puts 'Ich bin nach dem raise.' rescue puts 'Ich bin gerettet.' end puts 'Ich bin nach dem begin-Block.'

Das obige Beispiel gibt aus:

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

Eine weitere DemonstrationraiseAnwendungsbeispiel:

Beispiele

#!/usr/bin/ruby begin raise 'Eine Testausnahme.' rescue Exception => e puts e.message puts e.backtrace.inspect end

Das obige Beispiel gibt aus:

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

Verwendung derensure-Anweisung

Manchmal, ob eine Exception ausgelöst wird oder nicht, müssen Sie sicherstellen, dass eine Verarbeitung abgeschlossen wird, wenn der Codeblock endet. Zum Beispiel haben Sie beim Eintritt möglicherweise eine Datei geöffnet, und wenn Sie den Block verlassen, müssen Sie sicherstellen, dass die Datei geschlossen wird.

ensureDie ensure-Klausel macht genau das. ensure wird nach der letzten rescue-Klausel platziert und enthält einen Codeblock, der immer ausgeführt wird, wenn der Block endet. Es spielt keine Rolle, ob der Block normal beendet wird, ob er eine Exception auslöst und behandelt, oder ob er aufgrund einer nicht abgefangenen Exception beendet wird,ensureder Block wird immer ausgeführt.

Syntax

begin #.. verarbeiten #.. eine Exception auslösen rescue #.. Fehler behandeln ensure #.. schließlich Ausführung sicherstellen #.. dies wird immer ausgeführt end

Beispiele

begin raise 'Eine Test-Exception.' rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "Ausführung wird sichergestellt" end

Das obige Beispiel gibt aus:

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

Verwendung derelse-Anweisung

Wenn eineelse-Klausel angegeben wird, wird sie im Allgemeinen nach derrescue-Klausel platziert, vor jeglichemensurebefore.

elseDer Rumpf der Klausel wird nur ausgeführt, wenn der Hauptteil des Codes keine Ausnahme auslöst.

Syntax

begin #.. verarbeiten #.. eine Exception auslösen rescue #.. Fehler behandeln else #.. ausführen, wenn keine Ausnahme ensure #.. abschließend Ausführung sicherstellen #.. dies wird immer ausgeführt end

Beispiele

begin #raise 'A test exception.' puts "I'm not raising exception" rescue Exception => e puts e.message puts e.backtrace.inspect else puts "Congratulations-- no errors!" ensure puts "Ensuring execution" end

Das obige Beispiel gibt aus:

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

Mit der Variable $! können Sie die ausgelöste Fehlermeldung erfassen.

Catch und Throw

Der Ausnahmemechanismus von raise und rescue kann die Ausführung abbrechen, wenn ein Fehler auftritt. Manchmal müssen Sie während der normalen Verarbeitung aus tief verschachtelten Strukturen herausspringen. Hier kommen catch und throw ins Spiel.

catchdefiniert einen Block, der den angegebenen Namen (der ein Symbol oder String sein kann) als Label verwendet. Der Block wird normal ausgeführt, bis er auf ein throw trifft.

Syntax

throw :lablename #.. dies wird nicht ausgeführt catch :lablename do #.. catch, das nach dem Auftreten eines throw ausgeführt wird endorthrow :lablename condition #.. dies wird nicht ausgeführt catch :lablename do #.. catch, das nach dem Auftreten eines throw ausgeführt wird end

Beispiele

Im folgenden Beispiel wird, wenn der Benutzer als Antwort auf eine beliebige Eingabeaufforderung '!' eingibt, ein throw verwendet, um die Interaktion mit dem Benutzer zu beenden.

Beispiele

def promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res end catch :quitRequested do name = promptAndGet("Name: ") age = promptAndGet("Alter: ") sex = promptAndGet("Geschlecht: ") # .. #Umgang mit Informationen end promptAndGet("Name:")

Das obige Programm erfordert menschliche Interaktion; Sie können es auf Ihrem Computer ausprobieren. Das obige Beispiel gibt Folgendes aus:

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

Klasse Exception

Rubys Standardklassen und Module lösen Ausnahmen aus. Alle Ausnahmeklassen bilden eine Hierarchie, einschließlich der Klasse Exception an der Spitze. Die nächste Ebene darunter besteht aus sieben verschiedenen Typen:

  • Unterbrechen
  • NoMemoryError
  • SignalException
  • ScriptError
  • StandardError
  • SystemExit

Fatal ist eine weitere Ausnahme auf dieser Ebene, aber der Ruby-Interpreter verwendet sie nur intern.

Sowohl ScriptError als auch StandardError haben einige Unterklassen, aber wir müssen diese Details hier nicht verstehen. Das Wichtigste ist, unsere eigenen Ausnahmeklassen zu erstellen, die Unterklassen der Klasse Exception oder ihrer Nachkommen sein müssen.

Sehen wir uns ein Beispiel an:

Beispiele

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

Nun, sehen Sie sich das folgende Beispiel an, das die obige Ausnahme verwenden wird:

Beispiele

File.open(path, "w") do |file| begin #Daten schreiben ... rescue #Ein Fehler ist aufgetreten raise FileSaveError.new($!) end end

Hier ist die wichtigste Zeile raiseFileSaveError.new($!). Wir rufen raise auf, um zu signalisieren, dass eine Ausnahme aufgetreten ist, und übergeben eine neue Instanz von FileSaveError, weil die spezifische Ausnahme dazu geführt hat, dass der Daten-Schreibvorgang fehlgeschlagen ist.

Weitere Erweiterungen