Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การทำงานกับข้อยกเว้นของ Ruby นอกบล็อกกู้ภัย

มักจะเป็นประโยชน์ที่จะได้รับข้อยกเว้นล่าสุด แม้ว่าโค้ดของคุณจะไม่ได้ควบคุมวงจรชีวิตของข้อยกเว้นนั้นก็ตาม ลองนึกภาพว่าคุณต้องการเพิ่มการตรวจจับข้อขัดข้องพื้นฐานให้กับแอปพลิเคชันของคุณ คุณต้องการบันทึกข้อมูลเพิ่มเติมเกี่ยวกับข้อขัดข้องที่เกิดขึ้นอันเป็นผลมาจากข้อยกเว้นที่ตรวจไม่พบ

ขั้นตอนแรกคือการเพิ่มตัวจัดการที่ทำงานทุกครั้งที่แอปพลิเคชันของคุณออก ทำได้ง่ายมากโดยใช้วิธี at_exit ของเคอร์เนล Ruby

at_exit
  puts "the app exited"
end

แต่เราจะรู้ได้อย่างไรว่าการโทรกลับทางออกถูกเรียกใช้อันเป็นผลมาจากข้อยกเว้นหรือไม่ Ruby ให้ชื่อ $! . ที่เข้ารหัสลับ ตัวแปรระดับโลก มันมีข้อยกเว้นที่เพิ่งยกขึ้นล่าสุดที่เกิดขึ้นที่ใดที่หนึ่งในสแต็กการโทรปัจจุบัน

การใช้ $! . เป็นเรื่องเล็กน้อย เพื่อตรวจสอบว่าโปรแกรมกำลังออกจากโปรแกรมเนื่องจากข้อยกเว้น หน้าตาประมาณนี้:

at_exit do
 save_error_to_log($!) if $!         
end

ข้อจำกัดของ $!

ขออภัย $! เมธอดจะใช้ได้ก็ต่อเมื่อข้อยกเว้นเกิดขึ้นที่ใดที่หนึ่งในสแต็กการโทรปัจจุบัน หากคุณกู้คืนข้อยกเว้น ให้ลองเข้าถึง $! นอกเงื่อนไขการช่วยเหลือ คุณจะได้ศูนย์

begin        
 raise "x"       
rescue       
 puts $! # => RuntimeError           
end

puts $! # => nil         

นี่หมายความว่า $! ค่อนข้างไร้ประโยชน์ภายในเปลือกเช่น IRB บ่อยครั้งใน IRB ฉันจะเรียกใช้เมธอดและรับข้อยกเว้น บางครั้งฉันต้องการที่จะได้รับข้อยกเว้นของวัตถุนั้น แต่ $! ใช้ไม่ได้กับสิ่งนี้

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

ต้องใช้ภาษาอังกฤษ

บางทีคุณอาจพบชื่อตัวแปรเช่น $! ตาแข็งเล็กน้อย? โชคดีที่ Ruby มีโมดูลที่เรียกว่า "English" ซึ่งให้ตัวแปรทั่วโลกในเวอร์ชันภาษาอังกฤษ ซึ่งดูเหมือนหุ่นยนต์ cusswords

คำพ้องความหมายสำหรับ $! คือ $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 $~
$ละเว้น $=
$ARGV $*
$MATCH $&
$PREMATCH $`
$POSTMATCH $‘
$LAST_PAREN_MATCH $+