2012-06-27 27 views
6

Tôi cần phải dọn sạch một cá thể R để trả lại trạng thái virginal khi khởi động. Cho đến nay, những gì tôi đang làm là:Làm cách nào để xác định thứ tự nhập không gian tên trong [R]

On khởi động, ghi lại các gói nạp và không gian tên

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

Khi tôi cần để tuôn ra những ví dụ, tách từng gói nạp mà không có ở đó lúc khởi động:

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

Vấn đề là nếu tôi đã tải gói có nhiều không gian tên đã nhập, chẳng hạn như ggplot2, các không gian tên đó sẽ được tải và tôi phải dỡ chúng theo thứ tự nhập từ cấp cao xuống. Chỉ cần dỡ bỏ chúng một cách mù quáng không hoạt động, vì tôi nhận được "không gian tên‘ x ’được nhập bằng các lỗi‘ y ’,‘ z ’để không thể tải xuống được”.

Đây là tái sản xuất ví dụ:

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) 
    } 
} 

Có một số cách để tìm ra hệ thống phân cấp namespace nhập khẩu? Nếu có, thì tôi chỉ có thể đặt hàng vòng cuối cùng một cách chính xác ...

+4

Tôi đã từ bỏ phương pháp này một thời gian dài trước đây. AFAIK, tài liệu cho 'detach' nói rằng nó không được bảo đảm để hoạt động. Cách duy nhất được đảm bảo là bắt đầu một phiên mới. – Andrie

+0

Vâng, đáng tiếc là tôi không thể bắt đầu một phiên mới dưới rpy2 AFAICT - đây là một ứng dụng web có phiên R liên tục trong thiết kế hiện tại của nó. – Tarek

+1

Theo dõi nhận xét của @ Andrie, vài bình luận cuối cùng về câu trả lời cho [câu hỏi SO này] (http://stackoverflow.com/questions/11004018/how-can-a-non-imported-method-in-a- không đính kèm-gói-được-tìm-by-gọi-to-fun) có được tại một trong những lý do mà chỉ đơn giản là 'detach'ing sẽ không đáng tin cậy khôi phục phiên của bạn về trạng thái ban đầu của nó. –

Trả lời

0

Vì @Josh O'Brien đã đề cập không thể có môi trường trong sạch bằng cách tách hoặc dỡ bỏ không gian tên.

Nhưng để trả lời câu hỏi của bạn ở đây là một phương pháp đơn giản để dỡ bỏ tất cả các không gian tên theo đúng thứ tự bằng cách sử dụng 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, tôi đã cùng nhau đưa ra một giải pháp hacky cho một nhu cầu bị tấn công. Bất kỳ lời khuyên nào về cách làm điều này tốt hơn sẽ được đánh giá cao. Đặc biệt, tôi không hài lòng với nhiệm vụ <<- của đối tượng namespace_depths toàn cầu.

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, trong ví dụ tôi đã liên kết ở trên, điều này * vẫn * không loại bỏ các phương thức từ các gói đính kèm trước đó (trong trường hợp đó 'reorder.factor()' từ 'gmodels') đã được đăng ký trong' .__ S3MethodsTable__ . 'của các gói đính kèm (trong trường hợp đó là' số liệu thống kê'). –

+0

Cảm ơn vì đã làm rõ, Josh. May mắn thay, điều này là đủ tốt cho những gì tôi đang làm, và câu trả lời của sgibb là cách đơn giản hơn tôi. – Tarek

Các vấn đề liên quan