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