ใครมีตัวอย่าง / บทช่วยสอนเกี่ยวกับการจัดการข้อยกเว้นใน R? เอกสารอย่างเป็นทางการค่อนข้างสั้นมาก
ใครมีตัวอย่าง / บทช่วยสอนเกี่ยวกับการจัดการข้อยกเว้นใน R? เอกสารอย่างเป็นทางการค่อนข้างสั้นมาก
คำตอบ:
นอกจากคำตอบของ Shane ที่ชี้ให้คุณเห็นการสนทนา StackOverflow อื่น ๆ แล้วคุณสามารถลองใช้คุณลักษณะการค้นหารหัส คำตอบเดิมนี้ชี้ไปที่ Code Search ของ Google ได้ถูกยกเลิกไปแล้ว แต่คุณสามารถลองได้
สำหรับบันทึกก็มีเช่นกันtry
แต่tryCatch
อาจดีกว่า ฉันลองนับอย่างรวดเร็วที่ Google Code Search แต่ลองรับผลบวกเท็จมากเกินไปสำหรับคำกริยานั้นเอง แต่ดูเหมือนว่าtryCatch
จะใช้กันอย่างแพร่หลาย
โดยทั่วไปคุณต้องการใช้tryCatch()
ฟังก์ชัน ดูวิธีใช้ ("tryCatch") สำหรับรายละเอียดเพิ่มเติม
นี่คือตัวอย่างเล็กน้อย (โปรดทราบว่าคุณสามารถทำอะไรก็ได้ที่ต้องการโดยมีข้อผิดพลาด):
vari <- 1
tryCatch(print("passes"), error = function(e) print(vari), finally=print("finished"))
tryCatch(stop("fails"), error = function(e) print(vari), finally=print("finished"))
ดูคำถามที่เกี่ยวข้องเหล่านี้:
ฟังก์ชั่นtrycatch()
นี้ค่อนข้างตรงไปตรงมาและมีบทเรียนที่ดีมากมายเกี่ยวกับเรื่องนี้ คำอธิบายที่ดีเยี่ยมในการจัดการข้อผิดพลาดในการวิจัยสามารถพบได้ใน Hadley Wickham หนังสือขั้นสูง-Rและสิ่งที่ตามมาคือมากบทนำพื้นฐานในการwithCallingHandlers()
และwithRestarts()
ในขณะที่คำไม่กี่คำที่เป็นไปได้:
สมมติว่าโปรแกรมเมอร์ระดับต่ำเขียนฟังก์ชันเพื่อคำนวณค่าสัมบูรณ์ เขาไม่แน่ใจว่าจะคำนวณอย่างไร แต่รู้วิธีสร้างข้อผิดพลาดและสื่อถึงความไร้เดียงสาของเขาอย่างขยันขันแข็ง:
low_level_ABS <- function(x){
if(x<0){
#construct an error
negative_value_error <- structure(
# with class `negative_value`
class = c("negative_value","error", "condition"),
list(message = "Not Sure what to with a negative value",
call = sys.call(),
# and include the offending parameter in the error object
x=x))
# raise the error
stop(negative_value_error)
}
cat("Returning from low_level_ABS()\n")
return(x)
}
โปรแกรมเมอร์ระดับกลางยังเขียนฟังก์ชันเพื่อคำนวณค่าสัมบูรณ์โดยใช้low_level_ABS
ฟังก์ชันที่ไม่สมบูรณ์อย่างวิบัติ เขารู้ว่ารหัสระดับต่ำจะแสดงnegative_value
ข้อผิดพลาดเมื่อค่าx
เป็นลบและแนะนำวิธีแก้ปัญหาโดยการสร้างรหัสrestart
ที่ช่วยให้ผู้ใช้mid_level_ABS
สามารถควบคุมวิธีการmid_level_ABS
กู้คืน (หรือไม่) จากnegative_value
ข้อผิดพลาดได้
mid_level_ABS <- function(y){
abs_y <- withRestarts(low_level_ABS(y),
# establish a restart called 'negative_value'
# which returns the negative of it's argument
negative_value_restart=function(z){-z})
cat("Returning from mid_level_ABS()\n")
return(abs_y)
}
สุดท้ายโปรแกรมเมอร์ระดับสูงจะใช้mid_level_ABS
ฟังก์ชันเพื่อคำนวณค่าสัมบูรณ์และสร้างตัวจัดการเงื่อนไขซึ่งบอก
mid_level_ABS
ให้กู้คืนจากnegative_value
ข้อผิดพลาดโดยใช้ตัวจัดการรีสตาร์ท
high_level_ABS <- function(z){
abs_z <- withCallingHandlers(
# call this function
mid_level_ABS(z) ,
# and if an `error` occurres
error = function(err){
# and the `error` is a `negative_value` error
if(inherits(err,"negative_value")){
# invoke the restart called 'negative_value_restart'
invokeRestart('negative_value_restart',
# and invoke it with this parameter
err$x)
}else{
# otherwise re-raise the error
stop(err)
}
})
cat("Returning from high_level_ABS()\n")
return(abs_z)
}
จุดทั้งหมดนี้คือว่าด้วยการใช้withRestarts()
และwithCallingHandlers()
ฟังก์ชั่น
high_level_ABS
ก็สามารถที่จะบอกmid_level_ABS
วิธีการกู้คืนจากข้อผิดพลาดที่เกิดขึ้นโดยlow_level_ABS
ข้อผิดพลาดโดยไม่ต้องหยุดการดำเนินการ
mid_level_ABS
ซึ่งเป็นสิ่งที่คุณไม่สามารถทำอะไรกับtryCatch()
:
> high_level_ABS(3)
Returning from low_level_ABS()
Returning from mid_level_ABS()
Returning from high_level_ABS()
[1] 3
> high_level_ABS(-3)
Returning from mid_level_ABS()
Returning from high_level_ABS()
[1] 3
ในทางปฏิบัติlow_level_ABS
หมายถึงฟังก์ชันที่mid_level_ABS
เรียกใช้จำนวนมาก (อาจถึงล้านครั้ง) ซึ่งวิธีการจัดการข้อผิดพลาดที่ถูกต้องอาจแตกต่างกันไปตามสถานการณ์และตัวเลือกวิธีจัดการข้อผิดพลาดที่เฉพาะเจาะจงจะถูกปล่อยให้เป็นฟังก์ชันระดับสูงกว่า ( high_level_ABS
)
ฟังก์ชันรีสตาร์ทมีความสำคัญมากใน R ที่สืบทอดมาจาก Lisp จะมีประโยชน์หากคุณต้องการเรียกใช้ฟังก์ชันบางอย่างในร่างกายของลูปและคุณเพียงแค่ต้องการให้โปรแกรมดำเนินการต่อหากการเรียกฟังก์ชันยุบลง ลองใช้รหัสนี้:
for (i in 1:20) withRestarts(tryCatch(
if((a <- runif(1))>0.5) print(a) else stop(a),
finally = print("loop body finished!")),
abort = function(){})