Roc*_*nce 19 namespaces r package assign
我正在使用R包,其中有2个函数f1和f2(f2调用f1)
我希望覆盖函数f1.
由于R 2.15和包中命名空间的强制使用,如果我只是获取新函数,它确实可以在全局环境中使用(即在控制台中只调用f1(x)返回新结果).但是,调用f2仍将使用打包的函数f1.(因为命名空间修改了搜索路径,并按照"写入R扩展"教程中的说明对其进行了封装)
将f1替换为新命令的正确方法是什么?(除了再次构建包装!)这在几种情况下都很有用.例如,如果包中存在您尚未开发的错误.或者,如果您不想在日常开发过程中重新构建软件包.
我知道功能
assignInNamespace("f1",f1,ns="mypackage")
Run Code Online (Sandbox Code Playgroud)
但是,帮助页面?assignInNamespace有点令人讨厌,并且似乎不鼓励人们在不提供更多信息的情况下使用它,我在官方CRAN教程中找不到任何最佳实践建议.并在调用此函数后:
# Any of these 2 calls return the new function
mypackage::f1
getFromNamespace(x = "f1", envir = as.environment("package:mypackage"))
# while this one still returns the old packaged version
getFunction(name = "f1", where = as.environment("package:mypackage"))
Run Code Online (Sandbox Code Playgroud)
这非常令人不安.搜索路径如何受到影响?
现在我正在做一些丑陋的事情,比如修改lockEnvironment函数,这样library就不会锁定包命名空间,一旦我替换了f1,我可以在以后锁定它(这似乎不是一个好习惯)
所以基本上我有两个问题:
assignInNamespace在包命名空间(应该被锁定)的情况下究竟做了什么非常感谢您在那里分享您的经验.
编辑:对此问题感兴趣的人可能会发现此博客文章非常有趣.
这里有很多不同的案例.
如果它是别人的包中的错误
那么最好的做法是联系包维护者并说服他们修复它.这样每个人都能得到修复,而不仅仅是你.
如果在开发自己的软件包时出现问题,
那么您需要找到一个易于重建软件包的工作流程.就像使用devtools包和键入build(mypackage),或单击按钮(RStudio中的"Build&Reload"; Architect中的"R CMD build").
如果你只是想要对现有包有不同的行为
如果它不是这样的bug,或者包维护者不能进行你想要的修复,那么你将不得不维护自己的副本f1.使用assignInNamespace在现有包中覆盖它可以进行探索,但它有点hacky所以它不适合永久解决方案.
你最好的选择是创建自己的包含f1和的副本f2.这比听起来要少,因为你可以定义f2 <- existingpackage::f2.
回应评论:
第二种和第三种情况是有意义的,如果你是独自一人,但他们需要构建和安装在我的组织的情况下很棘手的软件包,因为软件包部署在几十台计算机上,我需要root访问权来更新软件包.
因此,请获取现有软件包源的副本,应用您的修补程序,并将其托管在您的公司网络或github或Bitbucket上.然后可以通过编程方式安装更新的包
install.packages("//some/network/path/mypackage_0.0-1.tar.gz", repos = NULL)
Run Code Online (Sandbox Code Playgroud)
要么
library(devtools)
install_github("mypackage", "mygithubusername")
Run Code Online (Sandbox Code Playgroud)
由于安装只是一行代码,因此您可以轻松地将其推送到任意数量的机器.您也不需要root访问权限 - 只需将软件包安装到不需要root访问权限即可写入的库文件夹中.(阅读Startup和.libPaths帮助页面,了解如何定义新库.)您需要对这些计算机进行网络访问,但我无法帮助您.与您的网络管理员或您的老板或任何可以获得您许可的人交谈.
如果函数在包中没有显式绑定:
rlang::env_unlock(env = asNamespace('mypackage'))
rlang::env_binding_unlock(env = asNamespace('mypackage'))
assign('f1', f1, envir = asNamespace('mypackage'))
rlang::env_binding_lock(env = asNamespace('mypackage'))
rlang::env_lock(asNamespace('mypackage'))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4238 次 |
| 最近记录: |