rstudio / reticulate

R Interface to Python
https://rstudio.github.io/reticulate
Apache License 2.0
1.66k stars 328 forks source link

R Studio Global Options Conflict with `use_virtualenv()` embedded in `.onLoad()` #1633

Open EvoLandEco opened 1 month ago

EvoLandEco commented 1 month ago

Problem

My R package can pass R CMD Check and local tests of package loading during installation. However, if I try to load my package using library(mypkg), R Studio global settings seem to conflict with my code insde the .onLoad().


How to Reproduce

In my R package, in .onLoad(), I have these lines:

## Code to configure the virtual environment and install pandas 

## Then
reticulate::use_virtualenv("env_name")
reticulate::source_python(system.file(paste0("model/", "import.py"), package = "mypkg"))

And in import.py I have:

import pandas as pd

In R Studio -> Global Options -> Python -> Python interpreter, if the path is set to a system level Python installation, I always get an error when loading my package:

library(mypkg)

Error: package or namespace load failed for ‘env_name’:
 .onLoad failed in loadNamespace() for 'mypkg', details:
  call: py_run_file_impl(file, local, convert)
  error: ModuleNotFoundError: No module named 'pandas'
Run `reticulate::py_last_error()` for details.

If I manually activate my virtual environment after this error, I get:

reticulate::use_virtualenv("env_name")

ERROR: The requested version of Python
('C:/Users/xxx/.virtualenvs/env_name/Scripts/python.exe') cannot be used, as
another version of Python
('C:/Users/xxx/AppData/Local/Programs/Python/Python310/python.exe') has
already been initialized. Please restart the R session if you need to attach
reticulate to a different version of Python.
Error in use_python(python, required = required) : 
  failed to initialize requested version of Python

If I restart R Studio and activate my virtual environment before loading my package, it works but there is a warning:

reticulate::use_virtualenv("env_name")

Warning message:
Previous request to `use_python("C:/Users/xxx/AppData/Local/Programs/Python/Python310/python.exe", required = TRUE)` will be ignored. It is superseded by request to `use_python("C:/Users/xxx/.virtualenvs/env_name/Scripts/python.exe") 

library(mypkg) # now it works

Solution


Question

  1. Why use_virtualenv() works manually but not inside .onLoad()?

  2. Is there a conflict between R Studio global settings and reticulate? Or, is it a bad practice to use use_virtualenv() and source_python() inside .onLoad()?

t-kalinowski commented 1 month ago

Thanks for opening. The default value of the required argument in use_virtualenv(), use_python(), and use_conda() is different within .onLoad(). It is required = TRUE in most contexts, except in .onLoad(), where it is required = FALSE.

This is primarily for historical reasons. The default used to be required = FALSE. However, when we changed the default to required = TRUE, we preserved the behavior of required = FALSE in .onLoad() to avoid introducing breaking changes in already published packages and because most R packages generally should not place hard requirements on a specific Python environment.

Additionally, we do not recommend using source_python() within .onLoad() because it modifies the user's global environment and forces reticulate to initialize Python, possibly before the user has an opportunity to specify which Python should be selected. Using import_from_path(delay_load = TRUE) might be a better approach.