何时使用导入/依赖的更好解释


148

编写R扩展 ”手册为何时使用导入或依赖提供了以下指导:

一般规则是

  • 仅在使用“库”(pkgname)加载软件包时仅需要名称空间的软件包必须在“导入”字段中列出,而不是在“依赖”字段中列出。
  • 必须附加才能成功使用库(pkgname)加载程序包的程序包,仅在“依赖”字段中列出。

有人可以对此提供更多的清晰度吗?我怎么知道何时我的软件包只需要加载名称空间,以及何时需要附加软件包?两者都有什么例子?我认为典型的程序包只是函数的集合,有时会调用其他程序包中的函数(其中一些工作已被编码)。以上是这种情况1还是2?

编辑

我写了一篇博客文章,其中包含有关此特定主题的部分(搜索“ Imports v Depends”)。视觉效果使其更容易理解。


1
当我开始计划模块时,您的博客文章告诉了我有关包装结构的所有信息。谢谢!
康拉德·鲁道夫

Answers:


143

"Imports""Depends"(比使用其他包装更安全)(并且使使用它的包装成为“更好的公民” "Depends")。

"Depends"指令的尝试,以确保从另一程序包的功能是可用的由其它包附加到主搜索路径(即,由返回的环境的列表search())。但是,如果稍后加载的另一个程序包在搜索路径上更早放置了一个名称相同的函数,则可以阻止此策略。Chambers(在SoDA中)使用函数的示例,"gam"可以在gammgcv包中找到该函数。如果加载了另外两个软件包,则其中一个依赖于gam,一个依赖于mgcv,调用所找到的功能gam()将取决于这两个软件包的连接顺序。不好。

一个"Imports"指令应该用于任何支持包,其功能将被放置在<imports:packageName>(后立即搜索<namespace:packageName>),而不是常规的搜索路径。如果以上示例中的任何一个软件包都使用了该"Imports"机制(在文件中也需要importimportFrom指令NAMESPACE),则可以通过两种方式来改善问题。(1)程序包本身将获得对使用哪个mgcv功能的控制。(2)通过使主搜索路径远离导入的对象,它甚至不会潜在地破坏另一个程序包对另一个mgcv函数的依赖性。

这就是为什么使用名称空间是一个好习惯的原因,为什么它现在由CRAN强制执行,并且(尤其是)为什么使用using "Imports"比使用using 更安全"Depends"


编辑添加了一个重要的警告:

一个不幸的是常见的例外上面的建议:如果你的包依赖于一个封装A本身"Depends"上的另一个包B,你的包可能需要附加A一个"Depends指令。

这是因为程序包A中的函数是在编写程序包时期望程序包B及其功能将附加到search()路径上的

"Depends"指令将加载和附着封装A,在该点包A自身的"Depends"指令将在链反应,导致包B被装载和连接的为好。A然后,包中的功能将能够找到B它们所依赖的包中的功能。

一个"Imports"指令将加载,但重视包装A和意志没有负载,也没有附加包B。("Imports"毕竟,期望程序包编写者正在使用名称空间机制,并且该程序包A"Imports"用于指向B需要访问的任何函数。)函数调用A依赖于程序包中函数的程序包中的任何函数B将因此失败。

仅有的两种解决方案是:

  1. A使用"Depends"指令使程序包附加程序包。
  2. 从长远来看,更好的方法是,与软件包的维护者联系,A并要求他们在构造其命名空间时做得更加认真(用这个相关答案中的Martin Morgan来说)。

1
最近问了一个类似的问题,并在最近与这些问题进行了激烈的角力后,这些都是微妙的且经常无法传达的概念。我在这里是指你的另一种解释:stackoverflow.com/questions/7880355/...
布莱恩·汉森

@BryanHanson-感谢您在该链接上写下笔记。ImportsDependsWRT版本要求之间的差异以及.Rd文件中示例的检查确实是微妙的,并且值得了解。
乔什·奥布莱恩

1
关于使用“ Depends”的依赖关系的警告是一件可怕的事情。这意味着我基本上不能在我的软件包中使用“导入”,除非其他人也都一样。=(
肯·威廉姆斯

我仍然不清楚的一件事是,如果我正在编写一个程序包,而我想这样做Imports: ggplot2,为什么我的程序包却找不到autoplot功能?显然Depends附加了的软件包库,ggplot2因此没有问题。例如,我有一个autoplot.myFunction() 使用@import ggplot2标签的功能,而我的包裹有,Imports: ggplot2但是我得到一个错误:Error in eval(expr, envir, enclos) : could not find function "autoplot"当我尝试使用它时。
nathaneastwood

1
@威廉谢谢。您当然是正确的,并且我已经编辑了答案以清除误导性内容。使这个问题复杂化的部分原因是,尽管OP参照的DependsImports部分来构造他的问题DESCRIPTION,但他实际上是在询问“导入”功能(而不是“依赖”功能)的含义。由于后一个问题是我试图回答的问题(而且-我怀疑-大多数搜索此问题的人都想知道什么),因此我将在其他方面将答案保持不变。
乔什·奥布莱恩

31

Hadley Wickham给出了一个简单的解释(http://r-pkgs.had.co.nz/namespace.html):

在其中列出软件包,DependsImports确保在需要时安装它。主要区别在于,Imports只需在装入包装的地方Depends附加即可。没有其他区别。[...]

除非有充分的理由,否则应始终在Importsnot中列出软件包Depends这是因为一个好的程序包是独立的,并且将对全局环境(包括搜索路径)的更改最小化。唯一的例外是如果您的软件包设计为与另一个软件包结合使用。例如,模拟包建立在纯素之上。如果没有素食主义者,这是没有用的,所以要加入Depends代替Imports。同样,ggplot2应该真正取决于比例,而不是导入比例。


15

SfDA中的钱伯斯说,当此程序包使用“命名空间”机制并且由于现在要求所有程序包都具有“命名空间”机制时,请使用“导入”,因此答案现在可能总是使用“导入”。过去,程序包可能没有实际使用名称空间就已加载,在这种情况下,您将需要使用Depends。


2
当在“导入”中指定了程序包并且我想在程序包中使用一个函数时,我自己的函数需要调用library(...)还是在搜索路径中所有可用的函数?另外,什么是SfDA?链接?
SFun28 2011年

2
数据分析软件springer.com/statistics/computanional+statistics/book / ... ...关于您的问题,我不知道该如何回答,但是您可以轻松地破解一个最小的测试包并找到答案根据经验...
Ben Bolker

1
SfDA ==“数据分析软件”。[65]在r-project.org/doc/bib/R-books.html上。如果某个软件包指定了另一个软件包,则在控制台上使用library()或require()时,应该会看到一条消息,告诉您有关depends(ency)和import(ations)的加载。是的,然后应该可以使用它们。
IRTFM 2011年

4
+1-这也是我的强烈印象。此外,<namespace:packageName>作为的一部分,将在导入后立即搜索导入中指定的包<imports:packageName>。不需要进一步调用library(),并且R不会在程序包加载时在控制台上通知您,除非Import找不到ed程序包。
乔什·奥布莱恩

5

这是一个简单的问题,可帮助您决定使用哪个:

您的软件包是否要求最终用户直接访问另一个软件包的功能?

  • 否->导入(最常见的答案)
  • 是->取决于

唯一应该使用“ Depends”的时间是您的软件包是另一个软件包的附件或伴侣时,最终用户将在其代码中同时使用软件包和“ Depends”软件包中的函数。如果最终用户仅与您的功能交互,而另一个包仅在后台进行工作,则改用“导入”。

需要注意的是,如果像往常一样将包添加到“导入”,则代码将需要使用完整的名称空间语法(例如dplyr::mutate()而不是just)引用该包中的函数mutate()。它使代码阅读起来有些笨拙,但是要付出更好的包装卫生代价却是很小的代价。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.