2012-06-27 10 views
6

Potrzebuję oczyścić instancję R, aby przywrócić ją do stanu początkowo uruchomionego. Do tej pory, co robię jest:Jak określić kolejność importu przestrzeni nazw w [R]

dniu premiery nagrać załadowanych pakietów i nazw

original_packages <- grep('^package:', search(), value = TRUE) 
original_namespaces <- loadedNamespaces() 

Kiedy trzeba przepłukać instancji, odłączyć każdego załadowanego pakietu, który nie był tam w chwili premiery:

for (pkg in grep('^package:', search(), value = TRUE)) { 
    if (! pkg %in% original_packages){ 
     detach(pkg, unload=TRUE, force=TRUE, character.only=TRUE) 
    } 
} 

problemem jest to, że jeśli są załadowane opakowanie z grupą importowanych nazw, takich jak ggplot2 te nazw pozostawać załadowany, i trzeba wyładować je w kolejności od importu z wysokiego poziomu w dół. Po prostu rozładowanie ich na ślepo nie działa, ponieważ otrzymuję "przestrzeń nazw" x "jest importowana przez" y "," z ", więc nie można rozładować" błędów.

Oto powtarzalne przykład:

original_packages <- grep('^package:', search(), value = TRUE) 
original_namespaces <- loadedNamespaces() 

library(ggplot2) 
library(plyr) 

loadedNamespaces() 

for (pkg in grep('^package:', search(), value = TRUE)) { 
    if (! pkg %in% original_packages){ 
     detach(pkg, unload=TRUE, force=TRUE, character.only=TRUE) 
    } 
} 

for (ns in loadedNamespaces()) { 
    if (! ns %in% original_namespaces){ 
     unloadNamespace(ns) 
    } 
} 

Czy istnieje jakiś sposób, aby zorientować się w hierarchii import namespace? Jeśli tak, to powinienem być w stanie prawidłowo zamówić ostatnią pętlę ...

+4

dałem się na tej metodzie dawno temu. AFAIK, dokumentacja dla 'detach' mówi, że nie ma gwarancji, że zadziała. Jedynym gwarantowanym sposobem jest rozpoczęcie nowej sesji. – Andrie

+0

Tak, niestety nie mogę rozpocząć nowej sesji pod adresem rpy2 AFAICT - jest to aplikacja internetowa, która ma trwałą sesję R w swoim obecnym projekcie. – Tarek

+1

Kontynuacja komentarza @ Andrie, ostatnie kilka uwag na temat odpowiedzi na [to pytanie SO] (http://stackoverflow.com/questions/11004018/how-can-a-non-imported-method-ina-a- nie-dołączony-pakiet-można-znaleźć-przez-wywołania-do-zabawy) uzyskać jeden z powodów, że po prostu "odłączanie" nie będzie niezawodnie przywrócić twoją sesję do jej pierwotnego stanu. –

Odpowiedz

0

Jak wspomniał @Josh O'Brien, nie można uzyskać czystego środowiska przez odrywanie lub usuwanie przestrzeni nazw.

Ale odpowiedzi na pytanie o to proste podejście do rozładunku wszystkich nazw w poprawnej kolejności za pomocą tools:::dependsOnPkgs:

## params: originalNamespaces is a list of namespaces you want to keep 
cleanNamespaces <- function(originalNamespaces) { 

    ## which namespaces should be removed? 
    ns <- setdiff(loadedNamespaces(), originalNamespaces) 

    ## get dependency list 
    dep <- unlist(lapply(ns, tools:::dependsOnPkgs)) 

    ## append namespaces to guarantee to fetch namespaces with 
    ## no reverse dependencies 
    ns <- c(dep, ns) 

    ## get namespace names in correct order to unload without errors 
    ns <- names(sort(table(ns), decreasing=TRUE)) 

    ## only unload namespaces which are attached 
    ns <- ns[ns %in% loadedNamespaces()] 

    ## unload namespaces 
    invisible(sapply(ns, unloadNamespace)) 
} 
0

Ok, zrzuciłem razem hacky rozwiązanie do pewnie hacky potrzeby. Jakakolwiek rada, jak to zrobić lepiej, byłaby doceniona. W szczególności nie jestem zbyt zadowolony z przypisania <<- globalnego obiektu namespace_depths.

original_packages <- grep('^package:', search(), value = TRUE) 
original_namespaces <- loadedNamespaces() 

library(ggplot2) 
library(plyr) 

loadedNamespaces() 

new_packages <- Filter(function(pkg) { ! pkg %in% original_packages }, grep('^package:', search(), value = TRUE)) 

new_namespaces <- Filter(function(ns) { ! ns %in% original_namespaces }, loadedNamespaces()) 

get_imports <- function(ns, depth) { 

    imports <- Filter(function(ns) { ! ns %in% original_namespaces }, names(getNamespaceInfo(ns, 'imports'))) 
    if (length(imports) == 0) { 
     if (is.null(namespace_depths[[ns]]) || namespace_depths[[ns]] < depth){ 
      namespace_depths[[ns]] <<- depth 
     } 
     return() 
    } 
    for (imported_ns in imports){ 
     get_imports(imported_ns, depth + 1) 
    } 
    if (is.null(namespace_depths[[ns]]) || namespace_depths[[ns]] < depth){ 
     namespace_depths[[ns]] <<- depth 
    } 
} 

namespace_depths <- list() 
sapply(new_namespaces, get_imports, 0) 

for (ns in names(namespace_depths)[order(unlist(namespace_depths))]) { 
    if (! ns %in% original_namespaces){ 
     unloadNamespace(ns) 
    } 
} 

for (pkg in new_packages){ 
    detach(pkg, unload=TRUE, force=TRUE, character.only=TRUE) 
} 
+0

FWIW, w powyższym przykładzie, to * nadal * nie pozbywa się metod z wcześniej dołączonych pakietów (w tym przypadku 'reorder.factor()' z 'gmodels'), które zostały zarejestrowane w' .__ S3MethodsTable__ .'s wciąż dołączonych pakietów (w tym przypadku 'stats'). –

+0

Dzięki za wyjaśnienie, Josh. Na szczęście jest to wystarczająco dobre dla tego, co robię, a odpowiedź sgibb jest o wiele prostsza niż moja. – Tarek