2009-09-18 81 views
78

如果我从命令行(R --slave script.R)运行一个很长的R脚本,如何才能让它在错误时给出行号?R脚本错误的行号?

我不想调试命令,如果在所有可能添加到脚本 - 我只想R键行为像大多数其他脚本语言...

+20

有没有更新?四年后,似乎问题仍然存在,尽管所有的主流R被采用。 – 2013-09-15 00:41:43

+0

我也有很长的R脚本,有很多小输出,我想打印(下划线)(下划线)LINE/FILE(下划线) (下划线)(行号和脚本名称),而不是将行号硬编码到源代码中。 – mosh 2016-11-18 16:05:55

+0

我不知道R内部是否真的有'行号'的概念。但是,它确实具有完成任务的概念,即顶级任务。例如,可以轻松定义一个任务处理程序来告诉哪个顶级任务失败。当然,对于那些拥有大型连锁店或大条件声明的人来说,这并不是很大的安慰。 – russellpierce 2017-06-22 12:50:05

回答

33

这不会给你的行号,但它会告诉你在哪里失败调用堆栈发生,这是非常有帮助的:

traceback() 

[编辑:]当在命令行中运行脚本,你将不得不跳过一个或两个电话,看traceback() for interactive and non-interactive R sessions

我不知道的另一种方式来做到这一点,没有通常的调试嫌疑人:

  1. 调试()
  2. 浏览器()
  3. 选项(错误=恢复),然后选择(误差= NULL )回复吧]

You might want to look at this related post.

[编辑:]对不起......刚才看到你在命令行中运行此。在这种情况下,我会建议使用选项(错误)功能。这里有一个简单的例子:

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

,只要你想在出错时您可以创建复杂的脚本,所以你只要决定你需要什么样的信息进行调试。否则,如果存在特定的关注区域(例如连接到数据库),则将它们包装在tryCatch()函数中。

10

R 2.10及更高版本即将支持此操作。邓肯默多克刚刚发布到R-devel的在2009年9月10日约findLineNum and 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 
+0

有每日r-devel来源(和Windoze的二进制文件)... – 2009-09-18 21:56:23

+0

谢谢。刚刚注册了r-devel邮件列表。我一直在避免r-help,因为它会阻塞我的收件箱(r-sig-finance已经这么做)。 – Shane 2009-09-19 16:01:33

+1

真的不明白这是如何从命令行工作,而不需要在R脚本中打字 – 2016-05-25 21:21:34

10

options(error=traceback)提供了有关领导到错误的线的内容多一点的信息。如果出现错误,它会导致回溯,对于某些错误,它会有行号,前缀为#。但是它被击中或错过,许多错误不会得到行号。

+0

对我来说这不太合适。我只有一个文件,并没有显示行号,只是说错误发生后没有可用的踪迹。 – 2016-03-24 23:42:59

+0

@MarkLakata记住这是从2012年开始的一个答案,这是5年前... – 2017-03-28 09:12:56

0

您可以通过设置做

options(show.error.locations = TRUE) 

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

+1

有关此选项的背景信息,请参阅https://stat.ethz.ch/R-manual/R-devel/library/base /html/options.html – 2016-10-12 10:52:27

+0

这用于工作,但因为不可靠而被禁用。我认为这是企图迫使你使用RStudio,它最终将是非免费的。 – 2017-03-28 06:48:22

+6

我对此表示怀疑。 R核心和RStudio是非常不同的组织,R核心尤其是开源软件。 – 2017-03-28 15:40:48

1

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

由于我配置了错误处理,所以错误处理还会创建一个包含错误发生时工作内存中所有对象的RData文件。此转储可使用load(),然后将各种环境,因为它们在误差时存在可以交互使用debugger(errorDump)被检查被读回成R。

我会注意到,我能够在堆栈内的任何自定义功能traceback()输出得到行号,但只有当我打电话source()在我的脚本中使用的任何自定义函数时使用的keep.source=TRUE选项。如果没有此选项,请按如下所示设置全局错误处理选项,将traceback()的完整输出发送到名为error.log的错误日志,但行号不可用。

这是我参加了我的工作流程的一般步骤,以及如何我能非交互式[R失败后访问内存转储和错误日志。

  1. 我把以下放在我从命令行调用的主脚本的顶部。这为R会话设置了全局错误处理选项。我的主要脚本被称为myMainScript.R。代码中的各行对它们进行评论,描述它们的功能。基本上,使用此选项,当R遇到触发stop()一个错误,它会创建一个RDATA(* .rda)转储目录~/myUsername/directoryForDump在所有活动的环境中工作记忆的文件,也写了一些有用的命名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()})) 
    
  2. 确保从主脚本和任何后续函数调用,随时随地的函数来源,选项keep.source=TRUE使用。也就是说,要获得一个函数,你可以使用source('~/path/to/myFunction.R', keep.source=TRUE)。这是traceback()输出包含行号所必需的。看起来您也可以使用options(keep.source=TRUE)在全局范围内设置此选项,但是我没有测试过这个选项是否有效。如果你不需要行号,你可以省略这个选项。

  3. 从终端(R外),呼叫使用Rscript myMainScript.R在批处理模式下的主要脚本。这将启动一个新的非交互式R会话并运行脚本myMainScript.R。已放置在myMainScript.R顶部的步骤1中给出的代码片段为非交互式R会话设置了错误处理选项。
  4. myMainScript.R执行中的某处遇到错误。这可能在主脚本本身,或深层嵌套几个功能。遇到错误时,将按照步骤1中的说明执行处理,并且R会话将终止。
  5. 在全局错误处理选项设置中,由'~/myUsername/directoryForDump'指定的目录中创建名为errorDump.rda的RData转储文件和名为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. 在您的休闲,你可以加载到errorDump.rda使用load('~/path/to/errorDump.rda')一个互动R对话。加载后,请拨打debugger(errorDump)以浏览任何活动环境中内存中的所有R对象。有关更多信息,请参阅debugger()上的R帮助。

该工作流在某些类型的生产环境中,你必须在命令行正在启动非交互式的R会话,你想保留意想不到的错误信息运行R是很大的帮助。将内存转储到错误发生时可用于检查工作内存的文件以及调用堆栈中错误的行号,可以快速调试导致错误的原因。