Список функций с установленным флагом отладки в R - PullRequest
11 голосов
/ 05 августа 2011

Я пытаюсь найти глобальный аналог 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"))

Ответы [ 5 ]

6 голосов
/ 05 августа 2011

Вот мой бросок в функцию 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)"
  • , по умолчанию просматривается весь путь поиска
3 голосов
/ 10 июля 2017

Это простой однострочник, использующий lsf.str:

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

Вы можете изменить окружение в функции, дополнительные аргументы см. В ?lsf.str.

2 голосов
/ 12 октября 2011

Начиная с исходного вопроса, я все больше и больше смотрю на Mark * Bravington's debug package .Если используется этот пакет, то check.for.traces() - это подходящая команда для перечисления тех функций, которые отлаживаются с помощью mtrace.

. Отладочный пакет стоит посмотреть, если вы проводите много времени с отладчиком R иразличные варианты trace.

1 голос
/ 13 февраля 2014

@ 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)
}
0 голосов
/ 13 октября 2016

Я постоянно попадаю в оконную раму 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())
  }
}

Я проверил их, и они работают довольно хорошо.Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...