问题 列出在R中设置调试标志的函数


我正试图找到一个全球对应的 isdebugged() 在R.我的场景是我有函数调用其他函数,所有这些都是我写的,我正在转向 debug() 在我的调试过程中打开和关闭不同的功能。但是,我可能会忘记将哪些功能设置为要调试。当我忘记并开始循环时,我可能会得到更多的输出(令人讨厌,但并不可怕),或者当某些需要时(可能不好)我可能没有输出。

我目前的方法是使用类似于下面的函数,我可以调用它 listDebugged(ls()) 或列出已加载库中的项目(以下示例)。这可能就足够了,但它要求我用工作区中的每个函数列表或加载的包中调用它。我可以包装另一个获得这些的函数。似乎应该有一种更简单的方法来直接“询问”调试函数或查询一些模糊的环境部分,它隐藏了调试标志集的函数列表。

所以,这是一个两部分的问题:

  1. 是否存在更简单的调用以查询设置了调试标志的函数?
  2. 如果没有,那么有什么诡计我忽略了吗?例如,如果一个包中的函数掩盖了另一个包,我怀疑我可能会返回一个误导性的结果。

我意识到我可以尝试另一种方法,即包装 debug 和 undebug 在函数内也维护一个隐藏的调试函数名列表。我还不相信这是安全的事情。

更新(8/5/11):我搜索了SO,并没有找到早期的问题。然而,SO的“相关问题”列表显示了这一点 一个类似的早期问题虽然这个问题的答案中的函数比@cbeleites提供的函数更冗长,更慢。较旧的问题也没有提供任何代码,而我做了。 :)

代码:

listDebugged    <- function(items){
    isFunction  <- vector(length = length(items))
    isDebugged  <- vector(length = length(items))

    for(ix in seq_along(items)){
        isFunction[ix]  <- is.function(eval(parse(text = items[ix])))
    }

    for(ix in which(isFunction == 1)){
        isDebugged[ix]  <- isdebugged(eval(parse(text = items[ix])))
    }
    names(isDebugged)   <- items
    return(isDebugged)
}

# Example usage
listDebugged(ls())
library(MASS)
debug(write.matrix)
listDebugged(ls("package:MASS"))

6319
2017-08-05 01:54


起源

在R base中,除了包装之外没有办法做那项工作 debug 功能。 - kohske


答案:


这是我在listDebugged函数中的抛出:

ls.deb  <- function(items = search ()){
  .ls.deb <-  function (i){
    f <- ls (i)
    f <- mget (f, as.environment (i), mode = "function",

               ## return a function that is not debugged
               ifnotfound = list (function (x) function () NULL)
               )

    if (length (f) == 0)
      return (NULL)

    f <- f [sapply (f, isdebugged)]
    f <- names (f)

    ## now check whether the debugged function is masked by a not debugged one
    masked <- !sapply (f, function (f) isdebugged (get (f)))

    ## generate pretty output format:
    ## "package::function"  and "(package::function)" for masked debugged functions
    if (length (f) > 0) {
      if (grepl ('^package:', i)) {
        i <- gsub ('^package:', '', i)
        f <- paste (i, f, sep = "::")
      }

      f [masked] <- paste ("(", f [masked], ")", sep = "")

      f
    } else {
      NULL
    }
  }


  functions <- lapply (items, .ls.deb)
  unlist (functions)
}
  • 我选择了一个不同的名称,因为输出格式只是调试功能(否则我很容易获得数千个功能)
  • 输出有形式 package::function (更确切地说 namespace::function 但是包很快就会有名称空间)。
  • 如果调试的函数被屏蔽,则输出为 "(package::function)"
  • 默认是查看整个搜索路径

6
2017-08-05 09:35



+1这很好,似乎工作。我现在正逐步介绍它,了解它正在做什么 f。聪明。 - Iterator
对我的监督:踩过去 debug() 是了解它正在做什么的更好方法。最好用的 debug 然而。 :) - Iterator
谢谢!我从这个函数中学到了几个新的功能和想法。 - Iterator


这是一个简单的单线使用 lsf.str

which(sapply(lsf.str(), isdebugged))

您可以在功能中更改环境,请参阅 ?lsf.str 更多的论点。


3
2017-07-10 10:26



检查所有附加功能的示例: names(which(sapply(unlist(lapply(search(), function(x) lsf.str(pos=x))), isdebugged))) - jbaums


从最初的问题开始,我一直在寻找越来越多的东西 Mark Bravington的 debug 包。如果使用该包,那么 check.for.traces() 是列出那些正在调试的函数的适当命令 mtrace

如果花费很多时间使用R调试器和各种调试包,那么调试包值得一看 trace 选项。


2
2017-10-12 14:36





@cbeleites我喜欢你的答案,但它对我不起作用。我得到了它的工作,但它没有上面的功能(没有递归检查,没有漂亮的打印)

require(plyr)
debug.ls <- function(items = search()){
  .debug.ls <- function(package){
    f <- ls(package)
    active <- f[which(aaply(f, 1, function(x){
        tryCatch(isdebugged(x), error = function(e){FALSE}, finally=FALSE)
      }))]
    if(length(active)==0){
      return(NULL)
    }
    active
  }

  functions <- lapply (items, .debug.ls)
  unlist (functions)
}

1
2018-02-13 01:53





我不断陷入困境 browser 窗框因为失败了 undebug 功能。所以我创建了两个函数并将它们添加到我的 .Rprofile。辅助函数非常简单。

require(logging)

# Returns a vector of functions on which the debug flag is set
debuggedFuns <- function() {
  envs <- search()
  debug_vars <- sapply(envs, function(each_env) {
    funs <- names(Filter(is.function, sapply(ls(each_env), get, each_env)))
    debug_funs <- Filter(isdebugged, funs)
    debug_funs
  })
  return(as.vector(unlist(debug_vars)))
}

# Removes the debug flag from all the functions returned by `debuggedFuns`
unDebugAll <- function(verbose = TRUE) {
  toUnDebug <- debuggedFuns()
  if (length(toUnDebug) == 0) {
    if (verbose) loginfo('no Functions to `undebug`')
    return(invisible())
  } else {
    if (verbose) loginfo('undebugging [%s]', paste0(toUnDebug, collapse = ', '))
    for (each_fn in toUnDebug) {
      undebug(each_fn)
    }
    return(invisible())
  }
}

我已经测试了它们,它运行得很好。希望这可以帮助!


0
2017-10-13 12:58