environment variables in reprex::reprex()

It is my understanding that R code passed on to reprex::reprex() is evaluated in a new, clean environment, so that no data or settings from the main R session are passed on.

reprex() takes the section of copied code and then runs rmarkdown::render() on it, which starts a fresh environment, and runs the code.

From the Magic reprex vignette

This does not seem to be true for environment variables though. Apparently, if I change an environment variable in my main R session, the change gets carried through to the reprex::reprex() environment.

Example: This code chunk was created with reprex::reprex()

Sys.getenv("R_TEST")
#> [1] ""

After I run Sys.setenv(R_TEST = "testit") in my main R session, reprex::reprex() shows this:

Sys.getenv("R_TEST")
#> [1] "testit"

Is this a bug or a feature?

Right, it uses your global environment in the call to rmarkdown::render(), which otherwise defaults to parent.frame().


From reprex_render.R:

This came when reprex became its own output format (see commit below), so I imagine it's intentional, but you could ask by filing an issue on the GitHub repo if you think it's in error.

1 Like

I want to add something about environment variables in R process and not just R environment.

Let's add that reprex is using callr to launch the render() in a new R session in the background.
It seems that callr inherits the environment variable from where the environment is launched.

Sys.getenv("R_TEST")
#> [1] ""
callr::r_safe(function() Sys.getenv("R_TEST"))
#> [1] ""
Sys.setenv(R_TEST = "test")
callr::r_safe(function() Sys.getenv("R_TEST"))
#> [1] "test"

callr calls processx::run that have a default on inheriting environment from parent process. See https://processx.r-lib.org/reference/run.html

I don't know it is intentional for callr or reprex to have this behavior but I hope this helps clarify where it comes from.

2 Likes

Right, environment variables are inherited by subprocesses.

1 Like

Thanks @hadley, but is that intentional/unavoidable for reprex::reprex()? From https://github.com/rstudio/rmarkdown/issues/1673 I gather that it should be possible to not inherit environment variables when rmarkdown::render()ing and by extension reprex::reprex()ing, but I might be reading that wrong.

At least in RStudio there seems be a way to do that (first paragraph in abovementioned post):

In RStudio, pressing the 'knit' button appears to render an Rmd in separate R process - such that the code execution environment is not contaminated by the global environment or search path of the user's interactive session.

And I thought that using {callr} should enable that, too? (Update: Only until I read @cderv's post above again).

That discussion doesn't talk about env vars at all. The language here is confusing - env vars (environment variable) are an operating system thing that's confusingly unrelated to R's environments.

1 Like

Thanks! I gather it is unavoidable then.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.