What is a reliable process for detaching an R package, in order to upgrade it?
Asked Answered
A

2

11

I have written a package that uses devtools to include internal data:

devtools::use_data(.data, internal = T, overwrite = T)

I recently changed that data and rebuilt the package. I want to upgrade that package on another machine that has the older package currently loaded:

detach('package:myPackage', unload=T)
remove.packages('myPackage')
install.packages(repos=NULL, 'myPackage.zip')

I check to see if the changes have gone through:

length(myPackage:::.data[[1]])
[1] 2169

Not what I was expecting... maybe a restart will help?

Restarting R session...
length(myPackage:::.data[[1]])
[1] 2179

Which is the expected result.

Reading the help for detach suggests that it can be flaky under some circumstances, for example:

If you use library on a package whose namespace is loaded, it attaches the exports of the already loaded namespace. So detaching and re-attaching a package may not refresh some or all components of the package, and is inadvisable.

My situation here is that I want to completely purge the loaded package so that I can update it. Is there a way to do this without restarting R?


EDIT 2016/10/28 - updated with a reproducible example below

  • tested on windows
  • requires devtools

...

# setup package in temp dir
pkg_dir <- file.path(tempfile(), 'dummy.test.pkg')
dir.create(pkg_dir, recursive=T)
devtools::create(pkg_dir)
setwd(pkg_dir)

# read description
desc <- readChar('DESCRIPTION', file.size('DESCRIPTION'))

# create and build package v01
.testval <- c(1,2,3)
devtools::use_data(.testval, internal=T, overwrite=T)
v01 <- sub('\\d+\\.\\d+\\.\\d+\\.\\d+', '0.0.0.1', desc, perl=T)
writeChar(v01, 'DESCRIPTION')
bin01 <- devtools::build(binary=T, path='.')

# create and build package v10
.testval <- c(4,5,6)
devtools::use_data(.testval, internal=T, overwrite=T)
v01 <- sub('\\d+\\.\\d+\\.\\d+\\.\\d+', '1.0.0.0', desc, perl=T)
writeChar(v01, 'DESCRIPTION')
devtools::build(binary=T, path='.')
bin10 <- devtools::build(binary=T, path='.')

# up to this point we haven't loaded either package
sessionInfo()

# install v01
install.packages(repos=NULL, bin01)
cat(dummy.test.pkg:::.testval)
# 1 2 3 (as expected)

# unload the package
unloadNamespace('dummy.test.pkg')

# install v10
install.packages(repos=NULL, bin10)
cat(dummy.test.pkg:::.testval)
# 1 2 3 (NOT 4 5 6 which we expected)

### restart R here ###
cat(dummy.test.pkg:::.testval)
# 4 5 6 (as expected)
Aileen answered 3/2, 2016 at 6:43 Comment(5)
Don't think you can do it safely. Is there a problem in restarting R?Steamer
It takes some time. I have the same 'problem'. I am curious what others do. What I do: remove package, close r, open r, install new package with same name.Bedrail
Two random-ish questions: 1) is there a variable in your environment named 'T'? 2) does a call to gc() after detach(...,unload=TRUE) do anything different?Yorktown
try unloading the namespace rather than detaching it.Talich
I don't have any variables named T. gc() doesn't solve the issue. unloadNamespace doesn't help either.Aileen
I
2

You are looking for unloadNamespace. I use it for the exact purpose you describe all the time.

Simply call in order:

# this may fail, see below
unloadNamespace("mypackage")
# if it succeeds you're all good

# updating the package
install.packages("mypackage")

# reloading the updated package
library("mypackage")

I never had any problem with that, whether installing from source/binary, from local/CRAN/github, with/without packrat, etc.

EDIT: this does not solve OP's particular problem which is updating the package data. However it works well for most simpler cases, e.g. updating some R code, so I am leaving the answer for future readers.

However, what may happen is that the target package was actually imported by other packages currently loaded. In this case, the unloading fails.

For example, I know this will fail in my current session:

> unloadNamespace("magrittr")
Error in unloadNamespace("magrittr") : 
  namespace ‘magrittr’ is imported by ‘stringr’, ‘customFunctions’, ‘dplyr’, ‘tidyr’ so cannot be unloaded

The solution here is to first unload (with unloadNamespace) all the packages importing "mypackage".

If there is a lot of importing packages, you may actually save time just restarting R. (Since you seem to be talking about a custom local package, this probably won't happen to you unless you have written other packages depending on it.)

Innerve answered 19/10, 2016 at 13:21 Comment(2)
Unfortunately unloadNamespace doesn't seem to help either. I've added a reproducible example to demonstrate.Aileen
@logworthy; Indeed, it does not behave as expected for data files (although it does work well in simpler scenarios, like just R code)... I have no idea why! I experimented quite a bit and could not get it to work at all. This is a peculiarity of R internals, potentially a bug. You'd be better off asking on the R-devel mailing list (r-project.org/mail.html) where you'll find the guys who know the most about such things. Best of luck!Innerve
S
0

If you do not want to restart the R session, a safe way to get the new data would be to save the data, e.g. by

save(.data, "data.rda")

copy them to to the other machine and there

load("data.rda")
Shoe answered 19/10, 2016 at 13:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.