我在工作中将几乎所有的R代码都写在包中(并使用git(。我大量使用devtools
,特别是load_all
的快捷方式等,因为我更新了软件包中使用的功能。 我对devtools
有一个粗略的了解,因为load_all
制作包的临时副本,我真的很喜欢这个用于测试包中函数更新的工作流程。
有没有一种很好的简单方法/工作流程来根据包运行模拟,同时开发它,而不会"破坏"这些模拟?
我怀疑有一个简单的解决方案,但我忽略了。
现在我做的是:
-
将包"mypackage"提升到可以运行模拟的地步。 复制包含项目的整个文件夹。 使用新的包名称"mypackage2"在复制的文件夹中运行模拟(。 运行包含
library(mypackage2)
但不包含library(mypackage)
的模拟脚本。这很烦人地意味着我需要将library(mypackage)
呼叫更新为library(mypackage2)
呼叫。 如果我使用library(mypackage)
运行模拟并避免使用library(mypackage2)
,那么我需要确保当前构建的mypackage
版本是"旧"版本,不会反映 2 中的更新。下面(但下面 2. 也需要重建包! 处理这一切变得混乱。 -
当模拟在复制的文件夹中运行时,我可以通过使用
load_all
或重建包来更新"mypackage"中的函数。 我经常需要重建包(即当测试包的更新不是一个可行的解决方案时,使用load_all
而不重建包(,因为我想测试运行具有doParallel
和foreach
等的小型并行模拟的函数(在 Windows 上(,我修改并想要测试的任何函数都需要子进程中最新构建的"mypackage",这些子进程会产生称为"mypackage"的新 R 进程。 我知道当一个包是在 R 中构建的时,它会存储在..RR-3.6.1library
中,当将来的 R 会话调用library(mypackage)
时,他们将使用该版本的包。
理想情况下,我希望能够做的是,在同一个原始文件夹中,使用 mypackage
版本运行模拟,然后在模拟停止/启动时更新包中的代码,确信我的开发更改不会破坏运行特定版本的包的模拟。
有没有一种简单的方法可以完成上述操作,而无需重新复制文件夹(并制作"mypackage2"之类的东西(?
谢谢
这里描述的问题有点类似于我面临的问题 在foreach中指定包位置
问题是,如果我使用"mypackage"运行一个需要几天时间的模拟,有很多调用foreach
,并在测试更改时更新和重建"mypackage",那么来自模拟的未来foreach
调用可能会拾取包的新更新版本,这将是一场灾难。
我认为另一个问题的答案确实适用, 但是您需要执行一些额外的步骤。
假设您有一个要测试的包版本。 您仍会为该版本创建特定文件夹,但将其留空。 在这里,我将以/tmp/mypkg2
为例。 在 RStudio 中打开项目时,执行:
withr::with_libpaths(c("/tmp/mypkg2", .libPaths()), devtools::install())
这会将该版本的包安装到提供的文件夹中。
然后你可以有一个包装脚本, 说wrapper.R
, 像这样:
pkg_path <- commandArgs(trailingOnly = TRUE)[1L]
cat("Using package at", pkg_path, "n")
.libPaths(c(pkg_path, .libPaths()))
library(doParallel)
workers <- makeCluster(detectCores())
registerDoParallel(workers)
# We need to modify the lib path in each worker too
parallel::clusterExport(workers, "pkg_path")
parallel::clusterEvalQ(workers, .libPaths(c(pkg_path, .libPaths())))
# ... Your code calling your package and doing stuff
parallel::stopCluster(workers)
之后,从命令行(R/RStudio 之外(, 您可以键入(假设路径中Rscript
(:
Rscript path/to/wrapper.R /tmp/mypkg2
这样,实际的测试代码可以保持不变 (包括拨打library
( 而R会在pkg_path
自动先搜索, 加载您的特定软件包版本, 然后在标准位置中搜索您可能具有的任何依赖项。
我不完全理解您的用例(至于为什么要这样做(,但是在测试包的两个版本时,我通常会做的是将最新版本推送到我在GitHub中的dev
分支,然后使用devtools::load_all()
来测试我当前正在做的事情。然后,通过使用 remotes::install_github()
并指定 dev 分支,您可以使用 mypackage::func
运行 GitHub 版本,并使用 func
运行 devtools 版本