Ruby Language
शुरुआती / बचाव के साथ आकर्षक अपवाद
खोज…
एक बुनियादी त्रुटि हैंडलिंग ब्लॉक
चलो दो संख्याओं को विभाजित करने के लिए एक फंक्शन बनाते हैं, जो इसके इनपुट के बारे में बहुत भरोसेमंद है:
def divide(x, y)
return x/y
end
यह बहुत सारे इनपुट के लिए ठीक काम करेगा:
> puts divide(10, 2)
5
लेकिन सब नहीं
> puts divide(10, 0)
ZeroDivisionError: divided by 0
> puts divide(10, 'a')
TypeError: String can't be coerced into Fixnum
हम जोखिम भरे डिवीजन ऑपरेशन को एक begin... end
त्रुटियों के लिए जाँच करने के लिए begin... end
ब्लॉक को रैप करके फ़ंक्शन को फिर से लिख सकते हैं, और यदि कोई समस्या है, तो एक संदेश और रिटर्न nil
आउटपुट के लिए एक rescue
खंड का उपयोग करें।
def divide(x, y)
begin
return x/y
rescue
puts "There was an error"
return nil
end
end
> puts divide(10, 0)
There was an error
> puts divide(10, 'a')
There was an error
त्रुटि सहेजना
यदि आप इसे rescue
खंड में उपयोग करना चाहते हैं तो आप त्रुटि को सहेज सकते हैं
def divide(x, y)
begin
x/y
rescue => e
puts "There was a %s (%s)" % [e.class, e.message]
puts e.backtrace
end
end
> divide(10, 0)
There was a ZeroDivisionError (divided by 0)
from (irb):10:in `/'
from (irb):10
from /Users/username/.rbenv/versions/2.3.1/bin/irb:11:in `<main>'
> divide(10, 'a')
There was a TypeError (String can't be coerced into Fixnum)
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/workspace.rb:87:in `eval'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/workspace.rb:87:in `evaluate'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/context.rb:380:in `evaluate'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:489:in `block (2 levels) in eval_input'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:623:in `signal_status'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:486:in `block in eval_input'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:246:in `block (2 levels) in each_top_level_statement'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:232:in `loop'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:232:in `block in each_top_level_statement'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:231:in `catch'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:231:in `each_top_level_statement'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:485:in `eval_input'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:395:in `block in start'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:394:in `catch'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:394:in `start'
/Users/username/.rbenv/versions/2.3.1/bin/irb:11:in `<main>'
विभिन्न त्रुटियों के लिए जाँच
यदि आप त्रुटि के प्रकार के आधार पर अलग-अलग काम करना चाहते हैं, तो एक तर्क के रूप में एक अलग त्रुटि प्रकार के साथ, कई rescue
खंडों का उपयोग करें।
def divide(x, y)
begin
return x/y
rescue ZeroDivisionError
puts "Don't divide by zero!"
return nil
rescue TypeError
puts "Division only works on numbers!"
return nil
end
end
> divide(10, 0)
Don't divide by zero!
> divide(10, 'a')
Division only works on numbers!
यदि आप rescue
खंड में उपयोग के लिए त्रुटि बचाना चाहते हैं:
rescue ZeroDivisionError => e
अन्य rescue
खंड में निर्दिष्ट प्रकार की त्रुटियों को पकड़ने के लिए बिना तर्क के rescue
खंड का उपयोग करें।
def divide(x, y)
begin
return x/y
rescue ZeroDivisionError
puts "Don't divide by zero!"
return nil
rescue TypeError
puts "Division only works on numbers!"
return nil
rescue => e
puts "Don't do that (%s)" % [e.class]
return nil
end
end
> divide(nil, 2)
Don't do that (NoMethodError)
इस मामले में, 2 से nil
को विभाजित करने की कोशिश करना ZeroDivisionError
या TypeError
, इसलिए इसे डिफ़ॉल्ट rescue
खंड द्वारा नियंत्रित किया जाता है, जो एक संदेश प्रिंट करता है हमें बताएं कि यह एक NoMethodError
था।
पुनः प्रयास किया जाएगा
rescue
खंड में, आप retry
से begin
खंड को चलाने के लिए retry
का उपयोग कर सकते हैं, संभवतः उस परिस्थिति को बदलने के बाद जो त्रुटि का कारण बनी।
def divide(x, y)
begin
puts "About to divide..."
return x/y
rescue ZeroDivisionError
puts "Don't divide by zero!"
y = 1
retry
rescue TypeError
puts "Division only works on numbers!"
return nil
rescue => e
puts "Don't do that (%s)" % [e.class]
return nil
end
end
यदि हम ऐसे पैरामीटर पास करते हैं जिन्हें हम जानते हैं कि एक TypeError
हो जाएगा, तो begin
खंड निष्पादित किया जाता है ("विभाजित करने के बारे में" यहां प्रिंट करके दिखाया गया है) और त्रुटि पहले की तरह पकड़ी गई है, और nil
वापस आ गया है:
> divide(10, 'a')
About to divide...
Division only works on numbers!
=> nil
लेकिन अगर हम पैरामीटर है कि एक कारण होगा पारित ZeroDivisionError
, begin
खंड निष्पादित किया जाता है, त्रुटि पकड़ा है, भाजक 0 से 1 के बदल गया है, और फिर retry
का कारण बनता है begin
एक साथ (ऊपर से) ब्लॉक फिर से चलाने के लिए, अब अलग y
। दूसरी बार के आसपास कोई त्रुटि नहीं है और फ़ंक्शन एक मान लौटाता है।
> divide(10, 0)
About to divide... # First time, 10 ÷ 0
Don't divide by zero!
About to divide... # Second time 10 ÷ 1
=> 10
यह देखना कि क्या कोई त्रुटि नहीं उठाया गया था
यदि आप कोई त्रुटि नहीं उठाते हैं, तो आप कोड के लिए किसी else
खंड का उपयोग कर सकते हैं।
def divide(x, y)
begin
z = x/y
rescue ZeroDivisionError
puts "Don't divide by zero!"
rescue TypeError
puts "Division only works on numbers!"
return nil
rescue => e
puts "Don't do that (%s)" % [e.class]
return nil
else
puts "This code will run if there is no error."
return z
end
end
यदि कोई त्रुटि है जो rescue
खंड में नियंत्रण स्थानांतरित करती है तो else
खंड नहीं चलता है:
> divide(10,0)
Don't divide by zero!
=> nil
लेकिन अगर कोई त्रुटि नहीं उठाई जाती है, तो else
खंड निष्पादित होता है:
> divide(10,2)
This code will run if there is no error.
=> 5
ध्यान दें कि यदि आप begin
खंड से लौटते हैं तो else
खंड को निष्पादित नहीं किया जाएगा
def divide(x, y)
begin
z = x/y
return z # Will keep the else clause from running!
rescue ZeroDivisionError
puts "Don't divide by zero!"
else
puts "This code will run if there is no error."
return z
end
end
> divide(10,2)
=> 5
कोड जो हमेशा चलना चाहिए
यदि आप हमेशा निष्पादित करना चाहते हैं तो कोड का उपयोग ensure
करें।
def divide(x, y)
begin
z = x/y
return z
rescue ZeroDivisionError
puts "Don't divide by zero!"
rescue TypeError
puts "Division only works on numbers!"
return nil
rescue => e
puts "Don't do that (%s)" % [e.class]
return nil
ensure
puts "This code ALWAYS runs."
end
end
त्रुटि होने पर यह ensure
जाएगा ensure
क्लॉज निष्पादित किया जाएगा:
> divide(10, 0)
Don't divide by zero! # rescue clause
This code ALWAYS runs. # ensure clause
=> nil
और जब कोई त्रुटि न हो:
> divide(10, 2)
This code ALWAYS runs. # ensure clause
=> 5
जब आप सुनिश्चित करना चाहते हैं कि यह क्लॉज़ उपयोगी है, उदाहरण के लिए, फ़ाइलें बंद हैं।
ध्यान दें कि, else
क्लॉज के विपरीत, यह ensure
करता है ensure
क्लॉज को begin
या rescue
क्लॉज मान से पहले निष्पादित किया जाता है । यदि यह ensure
क्लॉज में कोई return
जो किसी अन्य क्लॉज के return
वैल्यू को ओवरराइड करेगा!