[英]Use function from a package but different versions simultaneously
I have a multiple versions of the same package foo
(all with one function bar
), that I all want to use in the same script.我有同一个 package
foo
的多个版本(都有一个 function bar
),我都想在同一个脚本中使用。
Following this question, I can load v1
of the package with library("foo", lib.loc = "pkgs/v1")
.按照这个问题,我可以使用
library("foo", lib.loc = "pkgs/v1")
v1
v1。 But this loads all of the functions from the package.但这会加载 package 的所有功能。
Now I want to assign foo::bar
from the version v1 to bar_v1
and foo::bar
from version v2 to bar_v2
to call them independently.现在我想将 v1 版本的
foo::bar
分配给bar_v1
,将 v2 版本的foo::bar
::bar 分配给bar_v2
以独立调用它们。 But I do not see the option to only load one function of the library given a lib location (eg a solution would be to specify a lib.loc
in the function call bar_v1 <- foo::bar
).但是我没有看到在给定 lib 位置的情况下仅加载库的一个 function 的选项(例如,一种解决方案是在 function 调用
bar_v1 <- foo::bar
中指定一个lib.loc
)。
Is this possible in R?这在 R 中可能吗?
I have created a test package here github.com/DavZim/testPkg , which has one function foo
which prints the package version (hard coded).我在这里创建了一个测试 package github.com/DavZim/testPkg ,它有一个 function
foo
打印 package 版本(硬编码)。 The package has two releases , one for each version. package 有两个版本,每个版本一个。
To get the tar.gz files of the package, you can use this要获取 package 的 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")
Then to setup the folder structure in the form of然后以以下形式设置文件夹结构
pkgs/
0.1.0/
testPkg/
0.2.0/
testPkg/
I use我用
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)
Now the question is what do I write in myscript.R
?现在的问题是我在
myscript.R
中写了什么?
Ideally I would have something like this理想情况下我会有这样的东西
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"
Playing around with it, I thought something like this might work.玩弄它,我认为这样的事情可能会奏效。 But it doesn't...
但它不...
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!
Interestingly, if I swap around the versions to load 0.2.0 first then 0.1.0, I get this有趣的是,如果我交换版本以先加载 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"
1) Successive loads Assume that we have source packages for testPkg in the current directory and they are named testPkg_0.1.0.tar.gz and testPkg_0.2.0.tar.gz. 1) 连续加载假设我们在当前目录下有testPkg的源码包,它们的名字分别是testPkg_0.1.0.tar.gz和testPkg_0.2.0.tar.gz。 Now create pkgs, pkgs/0.1.0 and pkgs/0.2.0 directories to act as release libraries and then install those source packages into those libraries.
现在创建 pkgs、pkgs/0.1.0 和 pkgs/0.2.0 目录作为发布库,然后将这些源包安装到这些库中。
Now assuming each has a function foo
which does not depend on other objects in the package, load each package in turn, rename foo
, and detach/unload the package. Now both can be accessed under the new names.现在假设每个都有一个 function
foo
,它不依赖于 package 中的其他对象,依次加载每个 package,重命名foo
,然后分离/卸载 package。现在可以使用新名称访问两者。
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
2) Change package name Another approach is to install one release normally and then for the other release download its source, change its name in the DESCRIPTION file and then install it under the new name. 2) 更改package 名称另一种方法是正常安装一个版本,然后为另一个版本下载其源代码,在DESCRIPTION 文件中更改其名称,然后以新名称安装。 Then both can be used.
然后两者都可以使用。
Assuming testPkg_0.1.0.tar.gz and testPkg_0.2.0.tar.gz source packages both have function foo
and that the two tar.gz files are in current directory we can accomplish this as follows.假设 testPkg_0.1.0.tar.gz 和 testPkg_0.2.0.tar.gz源包都有 function
foo
并且这两个 tar.gz 文件在当前目录中,我们可以按如下方式完成。 Note that changer will both change the DESCRIPTION file to use name testPkgTest and the directory name of the source package to the same.请注意,更改器会将描述文件更改为使用名称 testPkgTest 并将源 package 的目录名称更改为相同的名称。
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"
3) import Below we suggested the import package but unfortunately, as was pointed out in the comments, the code below using this package does not actually work and imports the same package twice. 3)导入下面我们建议导入 package 但不幸的是,正如评论中指出的那样,下面使用这个 package 的代码实际上不起作用并且导入相同的 package 两次。 I have created an issue on the import github site.
我在导入 github 网站上创建了一个问题。 https://github.com/rticulate/import/issues/74
https://github.com/rticulate/import/issues/74
Suppose we have source packages mypkg_0.2.4.tar.gz and mypkg_0.2.5.tar.gz in the current directory and that each has a function myfun
.假设我们在当前目录中有源包 mypkg_0.2.4.tar.gz 和 mypkg_0.2.5.tar.gz 并且每个包都有一个 function
myfun
。 Then this will create a library for each, install them into the respective libraries and import myfun
from each.然后这将为每个库创建一个库,将它们安装到各自的库中并从每个库中导入
myfun
。 These will be located in A and B on the search path.这些将位于搜索路径上的 A 和 B 中。
Note that the import package should be installed but not loaded, ie no library(import)
statement should be used.请注意,import package 应该安装但不加载,即不应使用
library(import)
语句。 You may wish to read the documentation of the import package since variations of this are possible.您可能希望阅读 import package 的文档,因为它可能有变体。
# 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")
Another possibility is to put them both into imports (used by default) with different names另一种可能性是将它们都放入具有不同名称的导入(默认使用)
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.