सबसे हालिया अपवाद प्राप्त करने में सक्षम होना अक्सर उपयोगी होता है, भले ही आपका कोड उस अपवाद के जीवनचक्र को नियंत्रित न करे। कल्पना करें कि आप अपने एप्लिकेशन में बुनियादी क्रैश डिटेक्शन जोड़ना चाहते हैं। आप किसी अपवाद के परिणामस्वरूप होने वाली किसी भी दुर्घटना के बारे में अतिरिक्त जानकारी लॉग करना चाहेंगे।
पहला कदम एक हैंडलर जोड़ना है जो तब चलता है जब आपका एप्लिकेशन बाहर निकलता है। रूबी कर्नेल की at_exit विधि के माध्यम से ऐसा करना बहुत आसान है।
at_exit
puts "the app exited"
end
लेकिन हम कैसे जान सकते हैं कि अपवाद के परिणामस्वरूप निकास कॉलबैक लागू किया गया था या नहीं? खैर, रूबी गुप्त रूप से नामित $!
. प्रदान करता है वैश्विक चर। इसमें सबसे हाल ही में उठाया गया अपवाद है जो वर्तमान कॉल स्टैक में कहीं हुआ है।
$!
. का उपयोग करना आसान नहीं है यह पता लगाने के लिए कि किसी अपवाद के कारण प्रोग्राम से बाहर निकाला जा रहा है या नहीं। यह कुछ इस तरह दिखता है:
at_exit do
save_error_to_log($!) if $!
end
$!
. की सीमाएं
दुर्भाग्य से, $!
विधि केवल तभी काम करती है जब अपवाद वर्तमान कॉल स्टैक में कहीं हुआ हो। यदि आप कोई अपवाद बचाते हैं, तो $!
. तक पहुंचने का प्रयास करें बचाव खंड के बाहर, आपको शून्य मिलेगा।
begin
raise "x"
rescue
puts $! # => RuntimeError
end
puts $! # => nil
इसका मतलब है कि $!
आईआरबी जैसे खोल के अंदर बहुत बेकार है। अक्सर आईआरबी में, मैं एक विधि चलाऊंगा और अपवाद प्राप्त करूंगा। कभी-कभी मैं उस अपवाद वस्तु को पकड़ना चाहता हूं। लेकिन $!
इसके लिए काम नहीं करता।
irb(main):001:0> 1/0
ZeroDivisionError: divided by 0
from (irb):1:in `/'
irb(main):002:0> $!
=> nil
लगभग $! PRY के साथ
PRY $!
. की सीमाओं के आसपास हो जाता है अपना स्थानीय चर जोड़कर, _ex_
. इस चर में सबसे हाल का न आया हुआ अपवाद है।
[1] pry(main)> raise "hi"
RuntimeError: hi
from (pry):1:in `__pry__'
[2] pry(main)> _ex_
=> #<RuntimeError: hi>
PRY के ऐसा करने में सक्षम होने का कारण यह है कि PRY या IRB के अंदर वास्तव में कोई भी अपवाद नहीं है। शेल स्वयं अपवादों को पकड़ता है और उन्हें अच्छी तरह से स्वरूपित त्रुटि संदेशों के रूप में प्रदर्शित करता है।
मैंने नीचे दिए गए PRY स्रोत के प्रासंगिक बिट्स की प्रतिलिपि बनाई है। आप देख सकते हैं कि आपके आदेशों का मूल्यांकन करने वाला कोड एक प्रारंभ/बचाव/अंत ब्लॉक के अंदर लपेटा गया है। जब कोई बचाव योग्य अपवाद होता है, तो PRY अपवाद को self.last_exception में सहेजता है और बाद में इसे _ex_
को सौंपा जाता है ।
# Excerpted from the PRY source at https://github.com/pry/pry/blob/623306966bfa86890ac182bc8375ec9699abe90d/lib/pry/pry_instance.rb#L273
begin
if !process_command_safely(line)
@eval_string << "#{line.chomp}\n" if !line.empty? || !@eval_string.empty?
end
rescue RescuableException => e
self.last_exception = e
result = e
Pry.critical_section do
show_result(result)
end
return
end
अंग्रेज़ी ज़रूरी है
शायद आपको $!
. जैसे चर नाम मिलें आंखों पर थोड़ा सख्त? सौभाग्य से, रूबी में "अंग्रेजी" नामक एक मॉड्यूल शामिल है जो कई वैश्विक चरों के अंग्रेजी-भाषा संस्करण प्रदान करता है जो अन्यथा रोबोट कस्वर्ड की तरह दिखते हैं।
$!
. का पर्यायवाची $ERROR_INFO
है . आप इसका उपयोग कहीं भी कर सकते हैं जहां आप आमतौर पर $!
. का उपयोग करते हैं ।
require "English"
begin
raise "x"
rescue
puts $ERROR_INFO # => RuntimeError
end
और यद्यपि अधिकांश अन्य अंग्रेजी समकक्षों का इस ब्लॉग पोस्ट के विषय से कोई लेना-देना नहीं है, मैं उन्हें किक्स के लिए शामिल कर रहा हूं। अंग्रेजी चर बाईं ओर हैं। मूल दायीं ओर हैं।
$ERROR_INFO | $! |
$ERROR_POSITION | $@ |
$FS | $; |
$FIELD_SEPARATOR | $; |
$OFS | $, |
$OUTPUT_FIELD_SEPARATOR | $, |
$RS | $/ |
$INPUT_RECORD_SEPARATOR | $/ |
$ORS | $\ |
$OUTPUT_RECORD_SEPARATOR | $\ |
$INPUT_LINE_NUMBER | $. |
$NR | $. |
$LAST_READ_LINE | $_ |
$DEFAULT_OUTPUT | $> |
$DEFAULT_INPUT | $< |
$PID | $$ |
$PROCESS_ID | $$ |
$CHILD_STATUS | $? |
$LAST_MATCH_INFO | $~ |
$IGNORECASE | $= |
$ARGV | $* |
$MATCH | $& |
$PREMATCH | $` |
$POSTMATCH | $' |
$LAST_PAREN_MATCH | $+ |