簡體   English   中英

如何附加包含非導出功能的包?

[英]how to attach a package including the non-exported functions?

從外部包調試函數時,我經常發現自己將函數復制到新腳本中以添加我的更正,但我必須在腳本開頭添加一堆foo=extpack:::foo以便函數訪問包的內部函數。

在經常更改單行的情況下,克隆和構建包將是一種徹底的矯枉過正。

有沒有辦法附加包及其所有內部功能?

類似library(extpack, attach_nonexported=TRUE)

您可以通過執行以下操作從包命名空間中獲取所有函數作為環境:

getNamespace("ggplot2")

因此,您可以通過執行以下操作將它們附加到您的搜索路徑(類似於使用未導出的函數調用library ):

attach(getNamespace("ggplot2"))

如果您更喜歡列表中的它們,則可以執行

as.list(getNamespace("ggplot2"))

或者,如果您希望它們出現在全局工作區中,您可以執行以下操作:

list2env(as.list(getNamespace("ggplot2")), globalenv())

不用說,你應該只在交互式會話中做這種事情,而不是在編寫包時。

如果你真的想模擬一個庫調用,我們可以在包含所有函數的搜索路徑上創建一個“package:yourpkg”:

magrittr::as_pipe_fn
#> Error: 'as_pipe_fn' n'est pas un objet exporté depuis 'namespace:magrittr'
magrittr:::as_pipe_fn
#> function (expr, env) 
#> {
#>     eval(call("function", lambda_fmls, expr), env)
#> }
#> <bytecode: 0x0000000013917228>
#> <environment: namespace:magrittr>

attach_all <- function(pkg) {
  pkg <- as.character(substitute(pkg))
  pkg_long <- paste0("package:", pkg)
  eval(bquote(with(
    setNames(list(getNamespace(pkg)), pkg_long), 
    attach(.(as.symbol(pkg_long)))
  )))
}

attach_all(magrittr)

search()
#>  [1] ".GlobalEnv"        "package:magrittr"  "package:stats"    
#>  [4] "package:graphics"  "package:grDevices" "package:utils"    
#>  [7] "package:datasets"  "package:methods"   "Autoloads"        
#> [10] "tools:callr"       "package:base"
as_pipe_fn
#> function (expr, env) 
#> {
#>     eval(call("function", lambda_fmls, expr), env)
#> }
#> <bytecode: 0x0000000013917228>
#> <environment: namespace:magrittr>

reprex 包(v0.3.0) 於 2020 年 10 月 9 日創建


使用package:mypkg可能會讓您感到緊張,如果是這樣,請隨意更改此部分,結果將相同。

另一種方法是將未導出的函數附加到不同的環境,以便您可以在需要時獨立分離它:

attach_unexported <- function(pkg) {
  pkg <- as.character(substitute(pkg))
  all_funs <- lsf.str(asNamespace(pkg))
  exported <- getNamespaceExports(pkg)
  unexported_funs <- setdiff(all_funs, exported)
  pkg_long <- paste0(pkg, "_unexported")
  eval(bquote(with(
    setNames(list(mget(unexported_funs, asNamespace(pkg))), pkg_long), 
    attach(.(as.symbol(pkg_long)))
  )))
}

attach_unexported(magrittr)

search()
#>  [1] ".GlobalEnv"          "magrittr_unexported" "package:stats"      
#>  [4] "package:graphics"    "package:grDevices"   "package:utils"      
#>  [7] "package:datasets"    "package:methods"     "Autoloads"          
#> [10] "tools:callr"         "package:base"
as_pipe_fn
#> function (expr, env) 
#> {
#>     eval(call("function", lambda_fmls, expr), env)
#> }
#> <bytecode: 0x0000000013a05bd0>
#> <environment: namespace:magrittr>

`%>%`
#> Error in eval(expr, envir, enclos): objet '%>%' introuvable

reprex 包(v0.3.0) 於 2020 年 10 月 9 日創建

進行此類錯誤修復的最佳方法是將修改后的函數的環境設置為與原始環境相同的環境。 例如,修復extpack::badfn使用

badfn <- function(...) { ... } # new version in your global workspace

environment(badfn) <- environment(extpack::badfn)

這意味着它在調用時會看到私有函數,但它不會替換原始位置的extpack::badfn ,因此調用它的其他extpack函數仍會調用原始函數。 如果您希望他們改用您的電話,請使用

assignInNamespace("badfn", badfn, "extpack")

進行上述更改后。

如果其他一些包導入extpack::badfn ,它得到的將取決於操作的確切順序,所以在這種情況下,你最好咬緊牙關,用你的修復程序重建整個包。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM