如果我从命令行运行一个长R脚本(R --slave script.R),我怎样才能让它给出错误的行号?
如果可能的话,我不想将调试命令添加到脚本中 - 我只是希望R的行为与大多数其他脚本语言一样......
答案 0 :(得分:41)
这不会给你行号,但它会告诉你调用堆栈中发生故障的位置非常有帮助:
traceback()
[编辑:] 从命令行运行脚本时,您必须跳过一两个电话,请参阅traceback() for interactive and non-interactive R sessions
如果没有通常的调试嫌疑人,我不知道另一种方法:
You might want to look at this related post.
[编辑:] 抱歉...刚刚看到你从命令行运行它。在这种情况下,我建议使用选项(错误)功能。这是一个简单的例子:
options(error = quote({dump.frames(to.file=TRUE); q()}))
您可以根据需要在错误情况下创建详尽的脚本,因此您应该只决定调试所需的信息。
否则,如果您关注的是特定区域(例如连接到数据库),请将它们包装在tryCatch()函数中。
答案 1 :(得分:11)
执行options(error=traceback)
提供了有关导致错误的行内容的更多信息。如果出现错误,它会导致出现回溯,对于某些错误,它会有行号,前缀为#
。但它的命中或错过,很多错误都不会得到行号。
答案 2 :(得分:9)
R 2.10及更高版本即将支持此项。 Duncan Murdoch于2009年9月10日刚刚向r-devel发布关于findLineNum and setBreapoint:
的消息我刚刚为R-devel添加了一些功能来帮助 调试。
findLineNum()
找到哪个函数的哪一行 对应于特定的源代码行;setBreakpoint()
需要findLineNum
的输出,并调用trace()
来设置断点 那里。这些依赖于代码中的源参考调试信息。 这是
source()
读取的代码的默认值,但不适用于包。 要在包代码中获取源引用,请设置环境 变量R_KEEP_PKG_SOURCE=yes
或R内的集合options(keep.source.pkgs=TRUE)
,然后从源安装包 码。请阅读?findLineNum
,了解有关如何告知其搜索的详细信息 在包内,而不是将搜索限制在全局范围内 环境。例如,
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=)
这将打印
f step 2,3,2 in <environment: R_GlobalEnv>
你可以使用
setBreakpoint("<text>#3")
在那里设置断点。
代码中仍然存在一些限制(可能是错误);生病 正在修理这个
答案 3 :(得分:5)
您可以通过设置
来实现options(show.error.locations = TRUE)
我只是想知道为什么这个设置不是R的默认设置?它应该是,就像所有其他语言一样。
答案 4 :(得分:3)
指定用于处理非灾难性错误的全局R选项,以及用于保留错误信息并在失败后检查此信息的自定义工作流程。我目前正在运行R版本3.4.1。 下面,我已经包含了对我有用的工作流程的描述,以及我用来设置R中的全局错误处理选项的一些代码。
正如我配置的那样,错误处理还会创建一个RData文件,其中包含错误发生时工作内存中的所有对象。可以使用load()
将此转储读回到R中,然后可以使用debugger(errorDump)
以交互方式检查错误发生时存在的各种环境。
我会注意到,我能够从堆栈中的任何自定义函数的traceback()
输出中获取行号,但前提是在调用keep.source=TRUE
时使用了source()
选项我的脚本中使用的任何自定义函数。如果没有此选项,则按如下所示设置全局错误处理选项会将traceback()
的完整输出发送到名为error.log
的错误日志,但行号不可用。
以下是我在工作流程中采取的一般步骤,以及在非交互式R故障后我如何能够访问内存转储和错误日志。
我将以下内容放在我从命令行调用的主脚本的顶部。这将为R会话设置全局错误处理选项。我的主要脚本名为myMainScript.R
。代码中的各个行在它们描述它们的作用之后会有注释。基本上,使用此选项,当R遇到触发stop()
的错误时,它将在目录~/myUsername/directoryForDump
中的所有活动环境中创建工作内存的RData(* .rda)转储文件,并且还将写入一个名为error.log
的错误日志,其中包含一些有用的信息到同一目录。您可以修改此代码段以在错误时添加其他处理(例如,向转储文件和错误日志文件名等添加时间戳)。
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()}))
确保从主脚本和任何后续函数调用中,只要有源函数,就会使用选项keep.source=TRUE
。也就是说,要使用函数,您可以使用source('~/path/to/myFunction.R', keep.source=TRUE)
。这是traceback()
输出包含行号所必需的。看起来您也可以使用options( keep.source=TRUE )
全局设置此选项,但我没有对此进行测试以查看它是否有效。如果您不需要行号,则可以省略此选项。
Rscript myMainScript.R
以批处理模式调用主脚本。这将启动一个新的非交互式R会话并运行脚本myMainScript.R
。步骤1中给出的代码片段放在myMainScript.R
的顶部,为非交互式R会话设置错误处理选项。myMainScript.R
的某个地方遇到错误。这可能在主脚本本身,或嵌套了几个函数深。遇到错误时,将按照步骤1中的指定执行处理,R会话将终止。errorDump.rda
指定的目录中创建名为error.log
的RData转储文件和名为'~/myUsername/directoryForDump'
的错误日志。闲暇时,请检查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)
闲暇时,您可以使用errorDump.rda
将load('~/path/to/errorDump.rda')
加载到交互式R会话中。加载后,调用debugger(errorDump)
以浏览任何活动环境中内存中的所有R对象。有关详细信息,请参阅debugger()
上的R帮助。
在某些类型的生产环境中运行R时,此工作流程非常有用,您可以在命令行启动非交互式R会话,并且希望保留有关意外错误的信息。将内存转储到可用于在错误发生时检查工作内存的文件的能力,以及在调用堆栈中具有错误的行号,有助于对导致错误的错误进行快速的事后调试。
答案 5 :(得分:0)
首先是options(show.error.locations = TRUE)
,然后是traceback()
。错误行号将显示在#