Eine Lösung gefunden! Habe es aus dem Code von 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
Schrieb eine schöne Wrapper-Funktion dafür:
# 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
}
So wird es verwendet:
f <- function ()
{
str <- caller_info("Called from %f at %s#%l\n")
cat(str)
}
Die einzige (geringfügige) Einschränkung besteht darin, dass R , wenn es in Unterausdrücken wie cat(caller_info("Called from %f at %s#%l\n"))
oder aufgerufen wird, cat(paste0(caller_info("Called from %f at %s#%l\n")))
diese Unterausdrucksgegenstände verwirrend als Stapelebenen zählt, was es durcheinander bringt. Vermeiden Sie daher besser die Verwendung dieses Wrappers in Ausdrücken.
.traceback()
.getSrcref
,getSrcFilename
undgetSrcLocation
statt direkt auf den Attributen arbeiten. Das interne Format kann sich ändern.Es gibt keine einfachen Funktionen, mit denen Sie das bekommen, wonach Sie fragen, aber zu Debugging-Zwecken können Sie
browser()
eine Funktion aufrufen und dann denwhere
Befehl ausführen , um den aktuellen Aufrufstapel anzuzeigen. Zum Beispiel könnten Sie so etwas sehen:Dies gibt Standorte für einige der Anrufe an, jedoch nicht für alle.
Wenn Sie wirklich etwas wollen, das unterwegs gedruckt wird (wie die
__LINE__
und__FILE__
Makros in C / C ++), ist es etwas schwieriger. Dies druckt den aktuellen Speicherort:Nicht alle Funktionen haben Namen, und R-Funktionen wissen nicht, unter welchem Namen Sie sie aufgerufen haben, aber Sie können den aktuellen Aufruf mit sehen
sys.call()
. Das druckt also alles:was drucken könnte
sys.call
hat ein Argument, um den Stapel nach oben zu verschieben, aber ich kenne keine Möglichkeit, die Zeilennummerninformationen abzurufen.Sie können den Ort des Starts der Funktion abrufen, mit der der aktuelle Aufruf ausgeführt wurde
Hier wird der Code angezeigt, der den Anruf getätigt hat, aber die Zeilennummer gilt nur für die Funktion, von der er stammt. Es ist ein gutes Argument, um Ihre Funktionen kurz zu halten!
quelle
browser()
, möglicherweise ausgelöst durch einen Fehler oder eine Warnung, oder verwenden Siecat("Called from ",getSrcFilename(sys.function(-1)), " line ",getSrcLocation(sys.function(-1), "line"), "\n")
, um den Funktionsort und nicht den tatsächlichen Anrufort anzugeben.