R脚本行号错误?

如果我从命令行(R –slave script.R)运行一个长的R脚本,我怎么能得到它在错误的行号?

我不想添加debugging命令的脚本,如果可能的话 – 我只是希望R行为像大多数其他脚本语言…

这不会给你线路号码,但它会告诉你在调用堆栈中发生故障的位置非常有用:

traceback() 

[编辑:]从命令行运行脚本时,必须跳过一两个调用,请参阅traceback()以获取交互式和非交互式R会话

我不知道另一种方式来做这个没有通常的debugging嫌疑人:

  1. debugging()
  2. 浏览器()
  3. 选项(错误=恢复)[后面的选项(错误= NULL)来恢复]

你可能想看看这个相关的post。

[编辑:]对不起…只是看到你从命令行运行这个。 在这种情况下,我会build议使用选项(错误)function。 这是一个简单的例子:

 options(error = quote({dump.frames(to.file=TRUE); q()})) 

您可以根据错误情况精心制作脚本,因此您应该决定需要debugging的信息。

否则,如果有特定的领域(例如连接到数据库),然后将它们包装在tryCatch()函数中。

R 2.10及更高版本即将支持这一function。 Duncan Murdoch于2009年9月10日刚刚发布到r-devel关于findLineNum和setBreapoint :

 I've just added a couple of functions to R-devel to help with debugging. findLineNum() finds which line of which function corresponds to a particular line of source code; setBreakpoint() takes the output of findLineNum, and calls trace() to set a breakpoint there. These rely on having source reference debug information in the code. This is the default for code read by source(), but not for packages. To get the source references in package code, set the environment variable R_KEEP_PKG_SOURCE=yes, or within R, set options(keep.source.pkgs=TRUE), then install the package from source code. Read ?findLineNum for details on how to tell it to search within packages, rather than limiting the search to the global environment. For example, x <- " f <- function(a, b) { if (a > b) { a } else { b } }" eval(parse(text=x)) # Normally you'd use source() to read a file... findLineNum("<text>#3") # <text> is a dummy filename used by parse(text=) This will print f step 2,3,2 in <environment: R_GlobalEnv> and you can use setBreakpoint("<text>#3") to set a breakpoint there. There are still some limitations (and probably bugs) in the code; I'll be fixing thos 

执行options(error=traceback)提供有关导致错误的行内容的更多信息。 如果出现错误,会导致回溯出现,并且对于某些错误,它会包含行号,前缀为# 。 但是碰到或错过,很多错误都不会得到行号。

指定用于处理非灾难性错误的全局R选项以及定制​​的工作stream程,以保留有关错误的信息并在失败后检查此信息。 我目前正在运行R版本3.4.1。 下面,我已经包含了对我工作的工作stream的描述,以及我用来在R中设置全局error handling选项的一些代码。

正如我所configuration的那样,error handling还会创build一个RData文件,其中包含错误发生时工作内存中的所有对象。 这个转储可以使用load()读回到R中,然后可以使用debugger(errorDump)以交互方式检查错误发生时存在的各种环境。

我会注意到,我能够从堆栈中的任何自定义函数的traceback()输出中获取行号,但是只有在为我的脚本中使用的任何自定义函数调用source()时使用keep.source=TRUE选项。 如果没有这个选项,像下面那样设置全局error handling选项error.log traceback()的完整输出发送到一个名为error.log的错误日志,但行号不可用。

以下是我在工作stream程中采取的一般步骤,以及在非交互式R失败后如何访问内存转储和错误日志。

  1. 我把以下内容放在我从命令行调用的主脚本的顶部。 这将为R会话设置全局error handling选项。 我的主脚本叫做myMainScript.R 。 代码中的各个行后面都有评论,描述他们做了什么。 基本上,使用这个选项,当R遇到一个触发stop()的错误时,它将在目录~/myUsername/directoryForDump中的所有活动环境中创build一个工作内存的RData(* .rda)转储文件,并且还会写入一个错误将名为error.log日志logging一些有用的信息到同一个目录。 您可以修改此片段以添加其他error handling(例如,将时间戳添加到转储文件和错误日志文件名等)。

     options(error = quote({ setwd('~/myUsername/directoryForDump'); # Set working directory where you want the dump to go, since dump.frames() doesn't seem to accept absolute file paths. dump.frames("errorDump", to.file=TRUE, include.GlobalEnv=TRUE); # First dump to file; this dump is not accessible by the R session. sink(file="error.log"); # Specify sink file to redirect all output. dump.frames(); # Dump again to be able to retrieve error message and write to error log; this dump is accessible by the R session since not dumped to file. cat(attr(last.dump,"error.message")); # Print error message to file, along with simplified stack trace. cat('\nTraceback:'); cat('\n'); traceback(2); # Print full traceback of function calls with all parameters. The 2 passed to traceback omits the outermost two function calls. sink(); q()})) 
  2. 确保从主脚本和任何后续的函数调用中, keep.source=TRUE有函数来源,就使用keep.source=TRUE选项。 也就是说,为了获得一个函数,你可以使用source('~/path/to/myFunction.R', keep.source=TRUE)traceback()输出需要包含行号。 看起来你也可以使用options( keep.source=TRUE )在全局范围内设置这个选项,但是我没有testing过,看它是否有效。 如果您不需要行号,则可以省略此选项。

  3. 从terminal(R外部),使用Rscript myMainScript.R以批处理模式调用主脚本。 这将启动一个新的非交互式R会话并运行脚本myMainScript.R 。 已放置在myMainScript.R顶部的步骤1中给出的代码段设置了非交互式R会话的error handling选项。
  4. myMainScript.R的执行过程中遇到错误。 这可能是在主脚本本身,或嵌套的几个function很深。 遇到错误时,将按照步骤1中的指定执行处理,R会话将终止。
  5. 在全局error handling选项设置中的'~/myUsername/directoryForDump'指定的目录中创build一个名为errorDump.rda转储文件和一个名为error.log错误日志。
  6. 在您的闲暇时间,检查error.log查看有关错误的信息,包括错误信息本身和导致错误的完整堆栈跟踪。 这里是错误生成的日志的一个例子。 请注意#字符之后的数字是调用堆栈中各个点处错误的行号:

     Error in callNonExistFunc() : could not find function "callNonExistFunc" Calls: test_multi_commodity_flow_cmd -> getExtendedConfigDF -> extendConfigDF Traceback: 3: extendConfigDF(info_df, data_dir = user_dir, dlevel = dlevel) at test_multi_commodity_flow.R#304 2: getExtendedConfigDF(config_file_path, out_dir, dlevel) at test_multi_commodity_flow.R#352 1: test_multi_commodity_flow_cmd(config_file_path = config_file_path, spot_file_path = spot_file_path, forward_file_path = forward_file_path, data_dir = "../", user_dir = "Output", sim_type = "spot", sim_scheme = "shape", sim_gran = "hourly", sim_adjust = "raw", nsim = 5, start_date = "2017-07-01", end_date = "2017-12-31", compute_averages = opt$compute_averages, compute_shapes = opt$compute_shapes, overwrite = opt$overwrite, nmonths = opt$nmonths, forward_regime = opt$fregime, ltfv_ratio = opt$ltfv_ratio, method = opt$method, dlevel = 0) 
  7. 在您闲暇时,您可以使用load('~/path/to/errorDump.rda')加载到交互式R会话中。 一旦加载,调用debugger(errorDump)浏览任何活动环境中内存中的所有R对象。 有关更多信息,请参阅debugger()上的R帮助。

在某些types的生产环境中运行R,在命令行中启动了非交互式R会话并且希望保留关于意外错误的信息时,此工作stream非常有用。 将内存转储到可用于在出错时检查工作内存的文件的能力,以及调用堆栈中错误的行号,便于迅速debugging导致错误的原因。

你通过设置来做到这一点

 options(show.error.locations = TRUE) 

我只是想知道为什么这个设置不是R的默认值? 它应该像其他语言一样。