如何获取最后一个错误

时间:2016-05-01 11:18:08

标签: r error-handling

我可以使用.Last.value

获取最后一个计算值
2 + 2
## [1] 4
.Last.value
## [1] 4

我可以使用last.warning访问最新警告。

warning("!!!")
## Warning message:
## !!! 
last.warning
## $`!!!`
##  NULL

我可以使用geterrmessage()

获取最新的错误消息
stop("!!!")
## Error: !!!
geterrmessage()
## [1] "Error: !!!\n"

如果我事先知道可能会抛出错误,我可以使用tryCatch返回错误对象。

tryCatch(stop("!!!"), error = identity)
## <simpleError in doTryCatch(return(expr), name, parentenv, handler): !!!>

如何在抛出之后将最后一个错误检索为对象?

例如,如果我输入

stop("!!!")

然后我希望能够输入getlasterror()或类似内容并检索simpleError个对象。

1 个答案:

答案 0 :(得分:2)

现代方式

如果您是代码的作者,解决此问题的现代方法是使用abort()包。您使用last_error()抛出错误,然后使用library(rlang) f <- function() { abort("@@@") } f() ## Error: @@@ last_error() ## <error> ## message: @@@ ## class: `rlang_error` ## backtrace: ## ─base::withCallingHandlers(...) ## ─global::f() ## Call `summary(rlang::last_error())` to see the full backtrace g <- function() { msg <- "###" abort(msg) } g() ## Error: ### last_error() ## <error> ## message: ### ## class: `rlang_error` ## backtrace: ## ─base::withCallingHandlers(...) ## ─global::g() ## Call `summary(rlang::last_error())` to see the full backtrace h <- function() { err_fn <- abort err_fn("$$$") } h() ## Error: $$$ last_error() ## <error> ## message: $$$ ## class: `rlang_error` ## backtrace: ## ─base::withCallingHandlers(...) ## ─global::h() ## Call `summary(rlang::last_error())` to see the full backtrace 检索最后一个错误。

stop()

这方面的局限性在于它不能处理由tryCatch()生成的错误。

原始答案

根据David Arenburg的评论,您可以将get_last_error <- function() { tr <- .traceback() if(length(tr) == 0) { return(NULL) } tryCatch(eval(parse(text = tr[[1]])), error = identity) } 与追溯结合使用。

# before an error is thrown
get_last_error()
## NULL

# after an error at the top level
stop("!!!")
## Error: !!!
get_last_error()
## <simpleError in eval(expr, envir, enclos): !!!>

# after an error inside a function
f <- function() stop("@@@")
f()
## Error in f() : @@@
get_last_error()
## <simpleError in eval(expr, envir, enclos): @@@>

示例:

g <- function()
{
  msg <- "###"
  stop(msg)
}

g()
## Error in g() : ###
get_last_error()
## <simpleError in stop(msg): object 'msg' not found>

h <- function()
{
  err_fn <- stop
  err_fn("$$$")
}

h()
## Error in h() : $$$
get_last_error()
## <simpleError in eval(expr, envir, enclos): could not find function "err_fn">

限制:

当您重新评估错误代码时,所有变量都需要可用。因此,以下示例不起作用,例如:

options(error = dump.frames)

通过设置last.dump,错误发生时的调用堆栈存储在全局环境中名为last.dump[length(last.dump)]的变量中。环境debugger(last.dump)有时包含错误对象,有时包含会产生错误的参数。

<!DOCTYPE html> <html> <head> <title>EasyUI Drag-n-Drop Test</title> <style> body, html { width: 100%; height: 100%; overflow: hidden; padding: 3px; box-sizing: border-box; margin: 0; } </style> <!-- Load JQuery --> <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.min.js"></script> <!-- Load EasyUI Framework --> <script type="text/javascript" src="http://www.jeasyui.com/easyui/jquery.easyui.min.js"></script> <link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/themes/default/easyui.css"> <link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/themes/icon.css"> <!-- Load Other Javascript Modules --> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.1/fabric.min.js"></script> <!-- Direct / Inline Javascript for this Document --> <script type="text/javascript"> // Handle Tree & Canvas Drag & Drop Events function handleStartDrag(e) { console.log('handleStartDrag'); console.table(e); var data = e.dataTransfer.getData('text'); alert('Drag-n-Dropped ['+text+']'); return false; }; function handleStopDrag(e) { console.log('handleStopDrag'); console.table(e); return false; }; function handleDragEnter(e) { console.log('handleDragEnter'); console.table(e); return false; }; function handleDragOver(e) { console.log('handleDragOver'); console.table(e); return false; }; function handleDragLeave(e) { console.log('handleDragLeave'); console.table(e); return false; }; function handleDrop(e) { console.log('handleDrop'); console.table(e); var data = e.dataTransfer.getData('text'); alert('Drag-n-Dropped ['+text+']'); return false; }; function loadFilter(data) { var nodes = []; for(var i = 0; i < data.length; i++) { var node = data[i]; nodes.push({ id: node.id, text: node.name, attributes: node, }); } return nodes; }; function loadPropertyGrid(node) { node = node || {id: '', text: '', attributes: {id: '', name: '', address: '', city: '', state: '', zip: '', phone: ''}}; $('#pg').propertygrid('loadData', [ {name: "ID", value: node.attributes.id, group: "", editor: 'text'}, {name: "Name", value: node.attributes.name, group: "", editor: 'text'}, {name: "Address", value: node.attributes.address, group: "", editor: 'text'}, {name: "City", value: node.attributes.city, group: "", editor: 'text'}, {name: "State", value: node.attributes.state, group: "", editor: 'text'}, {name: "Zip", value: node.attributes.zip, group: "", editor: 'text'}, {name: "Phone", value: node.attributes.phone, group: "", editor: 'text'}, ]); $('#pg').propertygrid('fitColumns'); }; function getData() { return [ {id: 1, name: "Tom Jones", address: "123 Blah Lane", city: "Somewhereville", state: "XY", zip: "12345", phone: "123-456-7890"}, {id: 2, name: "Sally Sue", address: "162 Foobar Dr", city: "Blechtown", state: "QZ", zip: "98672", phone: "345-123-5432"}, {id: 3, name: "Ralph Slug", address: "1762 Uknow St", city: "Mumbleville", state: "WE", zip: "21763", phone: "828-462-1786"}, ]; }; function getPgColumns() { return [[ {field: 'name', title: 'Item', width: 30, sortable: true, resizeable: true}, {field: 'value', title: 'Value', width: 70, resizeable: true}, ]]; } //----------------------------------------------------------------- $(document).ready(function() { // Set up Fabric.Js Canvas var canvas = new fabric.Canvas('cv'); var gridWidth = 1000; // define canvas grid width var gridHeight= 1000; // define canvas grid height canvas.clear(); // Clear (remove) all objects off the canvase setSelectionStyle(); // Set canvase selection style drawGrid(gridWidth, gridHeight, 20); // Draw a grid on the canvas // Bind the event listeners for the canvas var canvasWrapper = document.getElementById('cv_wrapper'); canvasWrapper.addEventListener('startdrag', handleStartDrag, false); canvasWrapper.addEventListener('stopdrag', handleStopDrag, false); canvasWrapper.addEventListener('dragenter', handleDragEnter, false); canvasWrapper.addEventListener('dragover', handleDragOver, false); canvasWrapper.addEventListener('dragleave', handleDragLeave, false); canvasWrapper.addEventListener('drop', handleDrop, false); // Draw something on the canvas var grp = new fabric.Group([]); var r1 = new fabric.Rect({left: 0, top: 0, width: 50, height: 50, fill: '#f00'}); var r2 = new fabric.Rect({left: 25, top: 25, width: 50, height: 50, fill: '#00f'}); grp.addWithUpdate(r1); grp.addWithUpdate(r2); canvas.add(grp); canvas.renderAll(); loadPropertyGrid(); function setSelectionStyle() { canvas.selectionColor = 'rgba(0,255,0,0.3)'; canvas.selectionBorderColor = '#f33'; canvas.selectionLineWidth = 2; }; function drawGrid(gridWidth, gridHeight, gridSize) { // to manipulate grid after creation var grid = new fabric.Group([], { left: 0, top: 0, lockRotation: true, lockScalingX: true, lockScalingY: true, hasControls: false, hasBorders: false, hasRotatingPoint: false, lockMovementX: true, lockMovementY: true, selectable: false, }); // define presentation option of grid var lineOption = {stroke: 'rgba(0,0,0,.4)', strokeWidth: 1, selectable:false, strokeDashArray: [3, 3]}; // vertical lines for(var i = Math.ceil(gridWidth/gridSize); i--;){ grid.add( new fabric.Line([gridSize*i, 0, gridSize*i, gridHeight], lineOption) ); } // horizontal lines for(var i = Math.ceil(gridHeight/gridSize); i--;){ grid.add( new fabric.Line([0, gridSize*i, gridWidth, gridSize*i], lineOption) ); } // add group to canvas canvas.add(grid); }; }); </script> </head> <body> <div class="easyui-layout" style="width:100%;height:100%;"> <!-- WEST (LEFT SIDE) --> <div data-options="region:'west',split:true" title="EasyUI Tree Widget" style="width:240px;overflow:hidden"> <div class="easyui-layout" style="width:100%;height:100%"> <div data-options="region:'north',split:true" style="height:60%"> <!-- Network Device Tree --> <ul class="easyui-tree" data-options=" data: getData(), loadFilter: function(data) { return loadFilter(data); }, onClick: function(node){ loadPropertyGrid(node); }, dnd: true, onDragEnter: function(e){ handleDragEnter(e); }, onDragOver: function(e) { handleDragOver(e); }, onDragLeave: function(e) { handleDragLeave(e); }, onDrop: function(e) { handleDrop(e); }, "></ul> </div> <div data-options="region:'center'" title="EasyUI PropertyGrid" style="height:40%"> <!-- Property Grid --> <table id="pg" class="easyui-propertygrid" style="width:100%" data-options=" method:'get', showGroup:false, scrollbarSize:0, columns: getPgColumns(), "> </table> </div> </div> </div> <!-- CENTER --> <div data-options="region:'center',title:'Fabric.js Canvas',iconCls:'icon-ok'"> <div data-container="FabricCanvas" id="cv_wrapper"> <canvas id="cv" class="canvas-container" width="1000" height="1000"></canvas> </div> </div> </body> </html> 允许对堆栈进行交互式事后探索,作为获取错误对象的替代方法。