使用包中的功能但同时使用不同版本

Dav*_*vid 5 r r-package

我有同一个包的多个版本foo(全部具有一个函数bar),我都想在同一个脚本中使用它们。

在这个问题之后,我可以v1使用 加载包library("foo", lib.loc = "pkgs/v1")。但这会加载包中的所有函数。

现在我想foo::bar从版本 v1 分配到版本v2bar_v1foo::bar版本 v2 来bar_v2独立调用它们。但我没有看到在给定 lib 位置的情况下仅加载库的一个函数的选项(例如,解决方案是lib.loc在函数调用中指定 a bar_v1 <- foo::bar)。

这在 R 中可能吗?

微量元素

我在这里创建了一个测试包github.com/DavZim/testPkgfoo ,它有一个打印包版本(硬编码)的函数。该软件包有两个版本,每个版本一个。

要获取包的 tar.gz 文件,您可以使用此

# Download Files from https://github.com/DavZim/testPkg
download.file("https://github.com/DavZim/testPkg/releases/download/v0.1.0/testPkg_0.1.0.tar.gz", "testPkg_0.1.0.tar.gz")
download.file("https://github.com/DavZim/testPkg/releases/download/v0.2.0/testPkg_0.2.0.tar.gz", "testPkg_0.2.0.tar.gz")
Run Code Online (Sandbox Code Playgroud)

然后以以下形式设置文件夹结构

pkgs/
  0.1.0/
    testPkg/
  0.2.0/
    testPkg/
Run Code Online (Sandbox Code Playgroud)

我用

if (dir.exists("pkgs")) unlink("pkgs", recursive = TRUE)

dir.create("pkgs")
dir.create("pkgs/0.1.0")
dir.create("pkgs/0.2.0")

# install the packages locally
install.packages("testPkg_0.1.0.tar.gz", lib = "pkgs/0.1.0", repos = NULL)
install.packages("testPkg_0.2.0.tar.gz", lib = "pkgs/0.2.0", repos = NULL)
Run Code Online (Sandbox Code Playgroud)

现在的问题是我该写什么myscript.R

理想情况下我会有这样的东西

bar_v1 <- some_function(package = "testPkg", function = "foo", lib.loc = "pkgs/0.1.0")
bar_v2 <- some_function(package = "testPkg", function = "foo", lib.loc = "pkgs/0.2.0")

bar_v1() # calling testPkg::foo from lib.loc pkgs/0.1.0
#> [1] "Hello World from Version 0.1.0"

bar_v2() # calling testPkg::foo from lib.loc pkgs/0.2.0
#> [1] "Hello World from Version 0.2.0"
Run Code Online (Sandbox Code Playgroud)

非工作尝试

玩弄它,我想这样的东西可能会起作用。但它并不...

lb <- .libPaths()

.libPaths("pkgs/0.1.0")
v1 <- testPkg::foo
v1()
#> [1] "Hello from 0.1.0"

.libPaths("pkgs/0.2.0")
v2 <- testPkg::foo
v2()
#> [1] "Hello from 0.1.0"

.libPaths(lb)

v1()
#> [1] "Hello from 0.1.0"
v2()
#> [1] "Hello from 0.1.0"   #! This should be 0.2.0!
Run Code Online (Sandbox Code Playgroud)

有趣的是,如果我交换版本以先加载 0.2.0,然后加载 0.1.0,我会得到这个

lb <- .libPaths()

.libPaths("pkgs/0.2.0")
v1 <- testPkg::foo
v1()
#> [1] "Hello from 0.2.0"

.libPaths("pkgs/0.1.0")
v2 <- testPkg::foo
v2()
#> [1] "Hello from 0.2.0"

.libPaths(lb)

v1()
#> [1] "Hello from 0.2.0"
v2()
#> [1] "Hello from 0.2.0"
Run Code Online (Sandbox Code Playgroud)

G. *_*eck 5

1)连续加载假设当前目录下有testPkg的源码包,分别命名为testPkg_0.1.0.tar.gz和testPkg_0.2.0.tar.gz。现在创建 pkgs、pkgs/0.1.0 和 pkgs/0.2.0 目录作为发布库,然后将这些源包安装到这些库中。

foo现在假设每个包都有一个不依赖于包中其他对象的函数,依次加载每个包,重命名foo,并分离/卸载包。现在,两者都可以用新名称进行访问。

dir.create("pkgs")
dir.create("pkgs/0.1.0")
dir.create("pkgs/0.2.0")

install.packages("testPkg_0.1.0.tar.gz", "pkgs/0.1.0", NULL)
install.packages("testPkg_0.2.0.tar.gz", "pkgs/0.2.0", NULL)

library("testPkg", lib.loc = "pkgs/0.1.0")
fooA <- foo
detach(unload = TRUE)

library("testPkg", lib.loc = "pkgs/0.2.0")
fooB <- foo
detach(unload = TRUE)

fooA
fooB
Run Code Online (Sandbox Code Playgroud)

2) 更改包名称另一种方法是正常安装一个版本,然后为另一个版本下载其源代码,在描述文件中更改其名称,然后以新名称安装。那么两者都可以使用。

假设 testPkg_0.1.0.tar.gz 和 testPkg_0.2.0.tar.gz源码包都具有功能foo,并且这两个 tar.gz 文件位于当前目录中,我们可以按如下方式完成此操作。请注意,更改器会将描述文件更改为使用名称 testPkgTest 并将源包的目录名称更改为相同。

library(changer)

install.packages("testPkg_0.1.0.tar.gz", repos = NULL)

untar("testPkg_0.2.0.tar.gz")
changer("testPkg", "testPkgTest")
install.packages("testPkgTest", type = "source", repos = NULL)

testPkg::foo()
## [1] "Hello World from Version 0.1.0"
testPkgTest::foo()
## [1] "Hello World from Version 0.2.0"
Run Code Online (Sandbox Code Playgroud)

老的

3) import下面我们建议导入包,但不幸的是,正如评论中指出的那样,下面使用这个包的代码实际上不起作用,并且导入了同一个包两次。我在 import github 站点上创建了一个问题。 https://github.com/rticulate/import/issues/74


假设当前目录中有源包 mypkg_0.2.4.tar.gz 和 mypkg_0.2.5.tar.gz,并且每个源包都有一个函数myfun。然后这将为每个库创建一个库,将它们安装到各自的库中并myfun从每个库中导入。它们将位于搜索路径上的 A 和 B 中。

注意导入包应该安装但不加载,即不library(import) 应该使用任何语句。您可能希望阅读导入包的文档,因为可能存在变化。

# use development version of import -- the CRAN version (1.3.0) has
# a bug in the .library= argument
devtools::install_github("rticulate/import")

dir.create("mypkglib")
dir.create("mypkglib/v0.2.4")
dir.create("mypkglib/v0.2.5")

install.packages("mypkg_0.2.4.tar.gz", "mypkglib/v0.2.4", NULL)
install.packages("mypkg_0.2.5.tar.gz", "mypkglib/v0.2.5", NULL)

import::from("mypkg", .library = "mypkglib/v0.2.4", .into = "A", myfun)
import::from("mypkg", .library = "mypkglib/v0.2.5", .into = "B", myfun)

search()
ls("A")
ls("B")

get("myfun", "A")
get("myfun", "B")
Run Code Online (Sandbox Code Playgroud)

另一种可能性是将它们都放入具有不同名称的导入(默认使用)中

import::from("mypkg", .library = "mypkglib/v0.2.4", myfunA = myfun)
import::from("mypkg", .library = "mypkglib/v0.2.5", myfunB = myfun)

search()
ls("imports")
myfunA
myfunB
Run Code Online (Sandbox Code Playgroud)