R 获取函数中的浏览状态
我有这样一个函数:R 获取函数中的浏览状态,r,debugging,R,Debugging,我有这样一个函数: fun <- function() { browser() is_browsing() } 但是,如果我注释掉browser()行,或按c停止浏览,is\u browsing()应返回FALSE,如下所示: > fun() Called from: fun() Browse[1]> debug at #3: is_browsing() Browse[2]> TRUE > fun() Called from: fun() Brow
fun <- function() {
browser()
is_browsing()
}
但是,如果我注释掉browser()
行,或按c
停止浏览,is\u browsing()
应返回FALSE
,如下所示:
> fun()
Called from: fun()
Browse[1]>
debug at #3: is_browsing()
Browse[2]>
TRUE
> fun()
Called from: fun()
Browse[1]> c
FALSE
我读过关于debuggingState()
和isdebugged()
的文章,但它们对我的情况似乎没有多大帮助
仅供参考的实际情况是,在浏览时更新绘图或视图,但只有在浏览时才更新,如果不是,我最后只想打印/查看一次,以节省资源。文档中描述了,以及: 不只是调用browser(),而是调用它并设置browseText或browseCondition的参数
browser(text="foo")
然后,您可以检查条件以确定浏览器是否正在运行:
is_browsing<-function(n)
{
result = FALSE
result = tryCatch({
browserText(n=1)
result = TRUE
}, warning = function(w) {
#warning-handler-code
}, error = function(e) {
# error-handler-code
}, finally = {
#code you always want to execute
})
return (result)
}
然后注释掉对browser的调用(text=“foo”),并查看差异
编辑:
如果由于任何原因无法将参数传递给browser(),则可以改用debug:
或者您可以使用其他外部调试器设置值。
< P>从Romain代码中的想法开始,然后复制RCNTXT结构(加上内部使用的其他两个结构),我设法获得C++代码返回的内容为“代码> RJGlulalValue < C++代码看起来是这样的:> fun()
Called from: fun()
Browse[1]>
debug at #3: is_browsing()
Browse[2]>
TRUE
> fun()
Called from: fun()
Browse[1]> c
FALSE
#包括
#包括
#包括
外部无效*R_全局上下文;
typedef结构{int-tag,flags;联合{int-ival;双dval;SEXP-sxpval;}u;
}R_bcu t;
typedef结构{jmp_buf jmpbuf;int mask_已保存,已保存_mask;}sigjmp_buf[1];
类型定义结构RCNTXT{
结构RCNTXT*nextcontext;
int callflag;
sigjmp_buf cjmpbuf;
int cstacktop,evaldepth;
SEXP promargs、callfun、sysparent、call、cloenv、conexit;
无效(*cend)(无效*);
void*cendata;
void*vmax;
int intsusp、gcenabled、bcintactive;
SEXP-bcbody;
无效*bcpc;
SEXP handlerstack、restartstack;
结构RPRSTACK*prstack;
R_bcstack_t*nodestack;
R_bcstack_t*bcprotop;
SEXP-srcref;
int browserfinish;
SEXP返回值;
结构RCNTXT*跳转目标;
int跳线掩码;
}RCNTXT,*上下文;
//[[Rcpp::导出]]
Rcpp::List get\u RCNTXT(int级别){
RCNTXT*res=(RCNTXT*)R_GlobalContext;
如果(级别>1)res=res->nextcontext;
返回Rcpp::List::create(Rcpp::Named(“call_flag”)=res->callflag,
Rcpp::Named(“c_stack_top”)=res->cstacktop,
Rcpp::Named(“call_depth”)=res->evaldepth,
Rcpp::Named(“call_fun”)=res->callfun,
Rcpp::Named(“sys\u parent”)=res->sysparent,
Rcpp::Named(“call”)=res->call,
Rcpp::Named(“cloenv”)=res->cloenv,
Rcpp::Named(“conexit”)=res->conexit,
Rcpp::Named(“promargs”)=res->promargs,
Rcpp::Named(“intsus”)=res->intsus,
Rcpp::Named(“gcenabled”)=res->gcenabled,
Rcpp::Named(“bcintactive”)=res->bcintactive,
Rcpp::Named(“handlerstack”)=res->handlerstack,
Rcpp::Named(“restartstack”)=res->restartstack,
Rcpp::Named(“srcref”)=res->srcref,
Rcpp::Named(“browserfinish”)=res->browserfinish);
}
这使我们能够查看R\u Globalcontext
的内容:
get\u RCNTXT(1)
#>$call_标志
#> [1] 12
#>
#>$c_堆栈_顶部
#> [1] 4
#>
#>$call\u深度
#> [1] 1
#>
#>$call_fun
#>职能(级别)
#>.呼叫(,级别)
#>
#>
#>$sys\u父项
#>
#>
#>美元电话
#>获取\u RCNTXT(1)
#>
#>$cloenv
#>
#>
#>$conexit
#>空的
#>
#>$promargs
#>$promargs[[1]]
#>空的
#>
#>
#>$intsus
#> [1] 0
#>
#>$gcenabled
#> [1] 1
#>
#>$b保护性
#> [1] 0
#>
#>$handlerstack
#>空的
#>
#>$restartstack
#>空的
#>
#>$srcref
#>空的
#>
#>$browserfinish
#> [1] 0
不幸的是,browserfinish
字段只返回一个0,无论是否从browser
调用。但是,如果从browser
提示符调用get\u RCNTXT
函数,则restartstack
显示已从browser
调用该函数。这允许在C++代码已被导出时定义以下R函数:
is_browser这不是你想要的100%,但也许你知道如何解决你的问题了?我不熟悉C/C++ + R基础知识,但可能你可以超载<代码> Base:BuffServer()/<代码>
我希望这有助于:
list.parent_env <- function() {
ll <- list()
n <- 1
while (!environmentName(.GlobalEnv) %in%
environmentName(parent.frame(n))) {
ll <- c(ll, parent.frame(n))
n <- n + 1
}
return(ll)
}
listofenv2names <- function(env_list) {
names <- unlist(lapply(c(1:length(env_list)), function(i) {
attributes(env_list[[i]])$name
}))
return(names)
}
# https://stackoverflow.com/a/23891089/5784831
mybrowser <- function() {
e <- parent.frame()
attr(e, "name") <- "mybrowser_env"
assign("mybrowser_env", 1,
envir = parent.frame(),
inherits = FALSE, immediate = TRUE)
return(eval(quote(browser()), parent.frame()))
}
is_browsing <- function() {
env_list <- list.parent_env()
r <- "mybrowser_env" %in% listofenv2names(env_list)
print(r)
return(r)
}
subsubfun <- function() {
print("subsubfun")
b <- 2
is_browsing()
return(NULL)
}
subfun <- function() {
print("subfun")
a <- 1
is_browsing()
subsubfun()
return(NULL)
}
fun1 <- function() {
print("fun1")
is_browsing()
mybrowser()
for (i in 1:10) {
is_browsing()
}
is_browsing()
subfun()
return(NULL)
}
fun2 <- function() {
print("fun2")
is_browsing()
return(NULL)
}
fun1()
fun2()
使用浏览器时,提示会显示浏览级别:
浏览[1],浏览[2]
> browser()
Called from: top level
Browse[1]> browser()
Called from: top level
Browse[2]>
此浏览级别在main.C
中通过以下方式计算:
browselevel = countContexts(CTXT_BROWSER, 1);
其中CTXT\u BROWSER
是定义在defn.h
中的常数:
CTXT_BROWSER = 16
您可以使用此内部countContexts
功能获取您正在查找的信息:
正在浏览.cpp
#include <Rcpp.h>
#include <R.h>
#include <Rinternals.h>
using namespace Rcpp;
// [[Rcpp::export]]
int is_browsing() {
return Rf_countContexts(16,1);
}
#包括
#包括
#包括
使用名称空间Rcpp;
//[[Rcpp::导出]]
int是_浏览(){
返回Rf_countcontext(16,1);
}
测试:
library(Rcpp)
sourceCpp('is_browsing.cpp')
test <- function() {
is_browsing()
}
test()
#> [1] 0
browser()
#> Called from: eval(expr, envir, enclos)
test()
#> [1] 1
库(Rcpp)
sourceCpp('is_browsing.cpp')
测试[1]0
浏览器()
#>调用自:eval(expr、envir、enclose)
测试()
#> [1] 1
由(v0.3.0)于2020年8月29日创建
如果在函数中调用了浏览器,也可以工作:
test2 <- function() {
browser()
is_browsing()
}
test2()
Called from: test2()
Browse[1]> n
debug à #3 :is_browsing()
Browse[2]> n
[1] 1
test2n
debugá3:is#u browsing()
浏览[2]>n
[1] 1
如果您希望返回真/假,则Rcpp代码为:
#包括
#包括
#包括
//[[Rcpp::导出]]
Rcpp::LogicalVector是_browsing(){
返回Rf_countContexts(16,1)>0;
}
我认为,如果您可以检查当前的RCNTXT
结构R\u GlobalContext
(或上下文堆栈上最近的某个条目),就可以获得这些信息。我不知道是否有任何用户级别
library(Rcpp)
sourceCpp('is_browsing.cpp')
test <- function() {
is_browsing()
}
test()
#> [1] 0
browser()
#> Called from: eval(expr, envir, enclos)
test()
#> [1] 1
test2 <- function() {
browser()
is_browsing()
}
test2()
Called from: test2()
Browse[1]> n
debug à #3 :is_browsing()
Browse[2]> n
[1] 1