[英]How to get line number of a function call in R?
For debug purposes, I want to print a line number (and function name) of the place the current function was called from.出于调试目的,我想打印调用当前函数的位置的行号(和函数名称)。 How do I get this in R?我如何在 R 中得到这个?
I've seen a solution of getting the source file name But how to get the line number and function name?]我见过获取源文件名的解决方案但是如何获取行号和函数名?]
EDIT: I found how to get this data from traceback()
in some form, traceback is able to print it out, but I am not sure how to decode the information out of it:编辑:我找到了如何以某种形式从traceback()
获取这些数据,traceback 能够将其打印出来,但我不确定如何从中解码信息:
f <- function () {
traceback(x = 3, max.lines = 1)
}
g <- function()
{
f()
}
x <- g()
source("file.R") # file with this code
# 5: g() at file.R#20
# 4: eval(ei, envir)
# 3: eval(ei, envir)
# 2: withVisible(eval(ei, envir))
# 1: source("file.R")
str(x[[1]])
# chr "g()"
# - attr(*, "srcref")= 'srcref' int [1:8] 20 1 20 8 1 8 20 20
# ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x0000000013a31700>
Found a solution!找到了解决办法! Got it from the code of traceback():从 traceback() 的代码中得到:
f <- function ()
{
x <- .traceback(x = 1)
srcloc <- if (!is.null(srcref <- attr(x[[1]], "srcref"))) {
srcfile <- attr(srcref, "srcfile")
paste0("Called from ", x[[2]], ", at ", basename(srcfile$filename), "#", srcref[1])
}
cat(srcloc, "\n")
}
g <- function()
{
f()
}
g()
# Called from g(), at file.R#15
Wrote a nice wrapper function for it:为它编写了一个很好的包装函数:
# returns a list, unless fmtstring is specified
# level: 1 - caller of the caller of this function; 2 - its parent, 3 - its grand-parent etc.
# fmtstring: return format string: %f (function), %s (source file), %l (line)
#
# example: str <- caller_info("Called from %f at %s#%l\n")
# !!! it won't work with e.g. cat(caller_info("Called from %f at %s#%l\n"))
# or cat(paste0(caller_info("Called from %f at %s#%l\n"))) !!!
caller_info <- function (fmtstring = NULL, level = 1) # https://stackoverflow.com/q/59537482/684229
{
x <- .traceback(x = level + 1)
i <- 1
repeat { # loop for subexpressions case; find the first one with source reference
srcref <- getSrcref(x[[i]])
if (is.null(srcref)) {
if (i < length(x)) {
i <- i + 1
next;
} else {
warning("caller_info(): not found\n")
return (NULL)
}
}
srcloc <- list(fun = getSrcref(x[[i+1]]), file = getSrcFilename(x[[i]]), line = getSrcLocation(x[[i]]))
break;
}
if (is.null(fmtstring))
return (srcloc)
fmtstring <- sub("%f", paste0(srcloc$fun, collapse = ""), fmtstring)
fmtstring <- sub("%s", srcloc$file, fmtstring)
fmtstring <- sub("%l", srcloc$line, fmtstring)
fmtstring
}
This is how it's used:这是它的使用方式:
f <- function ()
{
str <- caller_info("Called from %f at %s#%l\n")
cat(str)
}
The only (minor) limitation is that when called in subexpressions like cat(caller_info("Called from %f at %s#%l\\n"))
or cat(paste0(caller_info("Called from %f at %s#%l\\n")))
, R confusingly counts these subexpression things as stack levels, which messes it up.唯一(次要)限制是,当在诸如cat(caller_info("Called from %f at %s#%l\\n"))
或cat(paste0(caller_info("Called from %f at %s#%l\\n")))
,R 混淆地将这些子表达式的东西算作堆栈级别,这把它搞砸了。 So better avoid the use of this wrapper in expressions.所以最好避免在表达式中使用这个包装器。
There aren't easy functions to give you what you're asking for, but for debugging purposes you can call browser()
in a function, then run the where
command to see the current call stack.没有简单的函数可以满足您的要求,但出于调试目的,您可以在函数中调用browser()
,然后运行where
命令以查看当前调用堆栈。 For example, you might see something like this:例如,您可能会看到如下内容:
where 1: calls()
where 2 at ~/temp/test.R#6: print(calls())
where 3 at ~/temp/test.R#9: f()
where 4: eval(ei, envir)
where 5: eval(ei, envir)
where 6: withVisible(eval(ei, envir))
where 7: source("~/temp/test.R", echo = TRUE)
This gives locations for a couple of the calls, but not all of them.这给出了几个调用的位置,但不是所有调用。
If you really want something that prints as you go (like the __LINE__
and __FILE__
macros in C/C++), it's a little harder.如果你真的想要一些可以随时打印的东西(比如 C/C++ 中的__LINE__
和__FILE__
宏),那就有点难了。 This prints the current location:这将打印当前位置:
cat("This is line ", getSrcLocation(function() {}, "line"),
" of ", getSrcFilename(function() {}))
Not all functions have names, and R functions don't know what name you called them under, but you can see the current call using sys.call()
.并非所有函数都有名称,R 函数不知道您用什么名称调用它们,但是您可以使用sys.call()
查看当前调用。 So this prints everything:所以这会打印所有内容:
cat("This is line ", getSrcLocation(function() {}, "line"),
" of ", getSrcFilename(function() {}),
" called as", deparse(sys.call()),
"\n")
which might print这可能会打印
This is line 3 of test.R called as f()
sys.call
has an argument to move up the stack, but I don't know of a way to get the line number information. sys.call
有一个向上移动堆栈的参数,但我不知道获取行号信息的方法。
You can get the location of the start of the function that made the current call using您可以使用以下方法获取进行当前调用的函数的开始位置
cat("Called from ", getSrcFilename(sys.function(-1)), " line ", getSrcLocation(sys.function(-1), "line"),
" as ", deparse(sys.call()), "\n")
which will show you the code that made the call, but the line number is only for the function it came from.这将向您显示进行调用的代码,但行号仅适用于它来自的函数。 It's a good argument for keeping your functions short!这是保持函数简短的好理由!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.