前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >63-R工具指南-19-用packrat把包和代码一起分享给其他人

63-R工具指南-19-用packrat把包和代码一起分享给其他人

作者头像
北野茶缸子
发布2021-12-17 11:05:18
1.1K0
发布2021-12-17 11:05:18
举报
文章被收录于专栏:北野茶缸子的专栏

参见:https://zhuanlan.zhihu.com/p/146355865[1]

与别人分享代码时,常常会因为不同人机器的R与R 包的版本差异,而导致了出现报错。

R 版本比较好控制,直接官网下一个就好了,可是各种R 包纷繁错乱,而且版本更是各有不同,如何能控制呢?

主要介绍packrat,来解决它。

packrat

packrat 可以帮助我们管理和R 包的相关需求,包括:

  • 便于分离:创建的项目中使用的R 包将独立于本来R 环境下的包;
  • 易于转移:我们可以将项目使用的R 包打包,这样无论是其他人,还是自己,在使用其他设备或平台的R 时,都可以避免版本产生的问题。
  • 善于避险:有时候,我们可能会因为某个R 包而牵一发动全身。比如安装A 包依赖B 包,需要更新C 包,这就可能改变我们本身目录中的R 包环境,一旦出现问题,各种依赖和版本问题非常麻烦,我们可以通过packrat 建立临时的“快照”,出问题直接恢复即可。

我们直接通过install 即可安装。

1) 进入packrat 模式

代码语言:javascript
复制
packrat::init()

我们可以对init 指定目录,如果不指定,则是在工作环境的默认目录下创建(getwd查看)一个属于packrat 的目录,其会自动下载并保存当前工作环境中已经加载的R 包到packrat 目录下:

代码语言:javascript
复制
> packrat::init()
Initializing packrat project in directory:
- "D:/R测试"

Adding these packages to packrat:
                _         
    BH            1.75.0-0
    BiocManager   1.30.10 
    R6            2.3.0   

这时候我们也会进入packrat 模式,此时包的读取都会在packrat 的目录中,而非本身R 包的目录,如果想要加载进入packrat 模式前未曾加载的包,则其会进行重新安装:

代码语言:javascript
复制
> .libPaths()
[1] "D:/01-工作数据集/Rtest/packrat/lib/x86_64-w64-mingw32/4.0.2"    
[2] "D:/01-工作数据集/Rtest/packrat/lib-ext/x86_64-w64-mingw32/4.0.2"
[3] "D:/01-工作数据集/Rtest/packrat/lib-R/x86_64-w64-mingw32/4.0.2"  

> pacman::p_load(conflicted) # 包名冲突报警
Installing package into ‘D:/01-工作数据集/Rtest/packrat/lib/x86_64-w64-mingw32/4.0.2’
(as ‘lib’ is unspecified)

可见,是实打实的装了包在里面:

2)一些巧操作

我们在用R 更新或安装包的可能会遇到各种依赖导致的问题,可以使用snapshot 在对包环境修改前进行保存:

代码语言:javascript
复制
packrat::snapshot()

如果发现对R 包操作后产生的意外不满意,可以使用restore 恢复,不过我这里发现一个小bug,即便我用clean 清楚掉了packrat 中的所有包,其还是显示:

代码语言:javascript
复制
> packrat::restore()
Already up to date.

当我们最终确定好了项目执行所需要的全部包,可以将其打包:

代码语言:javascript
复制
packrat::bundle()

但发现这里使用unbundle 后,还是发生报错(这个bug 先留个坑):

代码语言:javascript
复制
Error in normalizePath(bundle, winslash = "/", mustWork = TRUE) : 
  缺少参数"bundle",也没有缺省值packrat::unbundle(bundle = "../Rtest/packrat/bundles/Rtest-2021-04-19.tar.gz", where = ".") # 正确代码应该长这样

其他的一些操作包括get_opt 与set_opt 修改一些packrat 的配置:

代码语言:javascript
复制
> packrat::get_opts()
$auto.snapshot
[1] FALSE

$use.cache
[1] FALSE

$print.banner.on.startup
[1] "auto"

$vcs.ignore.lib
[1] TRUE

$vcs.ignore.src
[1] FALSE

$external.packages
character(0)

$local.repos
character(0)

$load.external.packages.on.startup
[1] TRUE

$ignored.packages
character(0)

$ignored.directories
[1] "data" "inst"

$quiet.package.installation
[1] TRUE

$snapshot.recommended.packages
[1] FALSE

$snapshot.fields
[1] "Imports"   "Depends"   "LinkingTo"

$symlink.system.packages
[1] TRUE

还有其他一些操作,可以创建一个用户自己的R 包分支:

代码语言:javascript
复制
Manage ad-hoc local repositories (note that these are a separate entity from CRAN-like repositories):

packrat::set_opts(local.repos = ...) can be used to specify local repositories; that is, directories containing (unzipped) package sources.
packrat::install_local() installs packages available in a local repository.
For example, suppose I have the (unzipped) package sources for digest located within the folder~/git/R/digest/. To install this package, you can use:

packrat::set_opts(local.repos = "~/git/R")
packrat::install_local("digest")
There are also utility functions for using and managing packages in the external / user library, and can be useful for leveraging packages in the user library that you might not want as project-specific dependencies, e.g. devtools, knitr, roxygen2:

packrat::extlib(): Load an external package.
packrat::with_extlib(): With an external package, evaluate an expression. The external package is loaded only for the duration of the evaluated expression, but note that there may be other side effects associated with the package's .onLoad, .onAttach and .onUnload calls that we may not be able to fully control.

ps:忽然感觉,packrat 和pacman,都是pac 打头的,hhh。

3)退出packcat 模式

通常来说的操作,先前的init,以及最后snapshot 之后,就可以bundle 自己的包了。

如果需要退出packrat 模式回到本来的包环境,直接off 一下退出即可:

代码语言:javascript
复制
packrat::off()

4)打包与拆包

后面探索了一下,发现unbundle 这个函数的正确使用方法了:

代码语言:javascript
复制
packrat::unbundle(bundle = "../Rtest/packrat/bundles/Rtest-2021-04-19.tar.gz", 
                  where = ".")

其中重要的两个参数bundle 指定压缩包所在的位置,where 用来选择需要存放该项目的路径。

惊讶的发现,它不仅打包了包,还打包了全部的代码。

现在市面上那些提供代码的文章,能力可行的情况下,直接用packrat 打包会不会更好,更便于传播?这其实也是一个开发者与使用者谁更方便的tradeoff。

5)一些操作流总结

  • 测试R 包更新的影响

直接init 创建新的环境,用snapshot 保存,接着操作,如果出问题就restore 回去。退出用off。

  • 将包和代码打包给别人

完成全部代码后,确保没问题后,init 创建,bundle 打包,off 退出。如果打包前不放心,可以用status 函数检查:

代码语言:javascript
复制
> packrat::status()

The following packages are referenced in your code, but are not present
in your library nor in packrat:

    beepr

You will need to install these packages manually, then use
packrat::snapshot() to record these packages in packrat.
Warning message:
In FUN(X[[i]], ...) :
  Package 'beepr' not available in repository or locally

别的电脑接受bundle 的压缩包后,在非R project 下,用unbundle 打开该包:

进入环境后,直接on 就可以操作了。

其他操作

checkpoint

参见:https://www.rdocumentation.org/packages/checkpoint/versions/0.4.10[2]

checkpoint 的使用就比较简单了:

代码语言:javascript
复制
checkpoint("2021-04-10")

它会从上述指定的日期获得快照。

checkpoint可以:

  • 创建一个快照文件夹~/.checkpoint用来存包。
  • 扫描我们的项目文件夹,通过library() and require()来确定我们用了哪些包
  • 从MRAN 安装包install.packages()到我们自己的快照文件夹
  • 将我们的CRAN镜像指向MRAN (修改options(repos))

创建和使用的代码是一样的。快照信息存在~/.checkpoint 但目前还是没有明白,其是如何读取或者与默认R 包安装目录相分离的。

docker

我们可以直接通过docker 获得别人的R 环境。

只是相比R 包管理,docker 的学习成本大了一些。

conda

可以参考下面这个文章:

惊艳 | RStuido server选择不同的R版本(conda中的不同R版本) - 云+社区 - 腾讯云 (tencent.com)[3]

但个人觉得conda 的缺点在于,会新安装一整套R 和R 的依赖,相对来说有点浪费空间。

参考资料

[1]https://zhuanlan.zhihu.com/p/146355865: https://zhuanlan.zhihu.com/p/146355865

[2]https://www.rdocumentation.org/packages/checkpoint/versions/0.4.10: https://www.rdocumentation.org/packages/checkpoint/versions/0.4.10

[3]惊艳 | RStuido server选择不同的R版本(conda中的不同R版本) - 云+社区 - 腾讯云 (tencent.com): https://cloud.tencent.com/developer/article/1845582

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 北野茶缸子 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • packrat
    • 1) 进入packrat 模式
      • 2)一些巧操作
        • 3)退出packcat 模式
          • 4)打包与拆包
            • 5)一些操作流总结
            • 其他操作
              • checkpoint
                • docker
                  • conda
                    • 参考资料
                相关产品与服务
                容器镜像服务
                容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档