Skip to content

Instantly share code, notes, and snippets.

@gaborcsardi
Last active July 16, 2019 00:15
Show Gist options
  • Save gaborcsardi/26ef4fd5ee9741f395cbde7f1ec4c448 to your computer and use it in GitHub Desktop.
Save gaborcsardi/26ef4fd5ee9741f395cbde7f1ec4c448 to your computer and use it in GitHub Desktop.
TGM 2019-07-15
---
title: "Some new features in processx and callr"
output: html_notebook
---
# Better errors in processx, callr, gh
## Better errors from C
```{r error = TRUE}
processx::run("foobar")
processx::run("/tmp")
```
Two portable files:
<https://github.com/r-lib/processx/blob/master/src/errors.c>
<https://github.com/r-lib/processx/blob/master/src/errors.h>
API:
```
R_THROW_ERROR("Failed to open file `%s`, path);
R_THROW_SYSTEM_ERROR("Failed to set permission on file '%s', path);
R_THROW_SYSTEM_ERROR_CODE(errorcode, ...);
```
## `errors.R` standalone file from processx
Supports `.Last.error` and `.Last.error.trace`:
```{r error = TRUE}
processx::run("foobar")
.Last.error
.Last.error.trace
```
### in gh
```{r error = TRUE}
gh::gh("/foobar")
.Last.error
.Last.error.trace
```
### in callr
```{r error = TRUE}
callr::r(function() library("xxx"))
.Last.error
.Last.error.trace
```
# `callr::r_session` debugger
```{r}
rs <- callr::r_session$new()
rs$run(function() Sys.getpid())
Sys.getpid()
```
```{r error = TRUE}
rs$run(function() knitr::knit("foo-bar"))
.Last.error
.Last.error.trace
```
Now call `rs$debug()` and see the help.
# Pseudo-terminal with processx
Useful for
- driving interactive programs / R code
- testing interactive R code
```{r}
r2 <- processx::process$new("R", pty = TRUE)
r2$poll_io(1000)
```
```{r}
cat(r2$read_output())
cat(r2$read_output())
```
```{r}
r2$write_input("yesno::yesno()\n")
r2$poll_io(-1)
```
```{r}
cat(r2$read_output())
cat(r2$read_output())
```
```{r}
r2$write_input("1\n")
r2$poll_io(1000)
```
```{r}
cat(r2$read_output())
cat(r2$read_output())
cat(r2$read_output())
```
# Memory mapped data transfer in callr
This needs the `feature/mmap` branch of callr.
```{r}
data <- list(a = 1:100, b = runif(1e7), c = charToRaw("foobar"))
```
```{r}
fun <- function(a, b, c) {
list(mean(a), median(b), rawToChar(c))
}
```
```{r}
system.time({
cl <- parallel::makePSOCKcluster(1)
parallel::clusterExport(cl, c("data", "fun"))
res <- parallel::clusterEvalQ(cl, do.call(fun, data))
})
```
```{r}
system.time(
res <- callr::r(fun, args = data)
)
```
```{r}
system.time(
res <- callr::r(fun, args = data, transfer = "mmap")
)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment