खोज…


एक बुनियादी त्रुटि हैंडलिंग ब्लॉक

चलो दो संख्याओं को विभाजित करने के लिए एक फंक्शन बनाते हैं, जो इसके इनपुट के बारे में बहुत भरोसेमंद है:

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 वैल्यू को ओवरराइड करेगा!



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow