Reticulate: Sourcing Python Scripts in Packages

Created on 14 Aug 2018  路  4Comments  路  Source: rstudio/reticulate

Hi,

Perhaps it is not wise but currently as a quick fix I use reticulate::source_python to load a Python function in .onLoad part. My problem is that function is not callable when the package is loaded...unless I define the environment (using envir parameter of source_python) as globalenv().

Is it possible to have the function in the package namespace?

I am very new to this package by the way. Though I needed a Python function and needed a quick fix.

Most helpful comment

@berkorbay Try importing your script as a module with reticulate::import_from_path using the .onLoad method:

In ./R/zzz.R:

my_fun <- NULL

.onLoad <- function(libname, pkgname) {
the_module <- reticulate::import_from_path(module = "my_fun", path = system.file("py", package = packageName()))
my_fun <<- the_module$my_fun
}

Then export your function in your package NAMESPACE with export(my_fun)

Original Post here: https://community.rstudio.com/t/build-package-namespace-dynamically-during-onload/4101

All 4 comments

I would recommend bundling your Python files within the inst/python folder of your package, and explicitly importing + using them as necessary. For example:

path <- system.file("python", package = "<pkg>")
module <- reticulate::import_from_path(<module>, path = path)

You could also add your package path to the Python module path, so it's looked up automagically:

library(reticulate)
path <- system.file("python", package = "<pkg>")
sys <- import("sys", convert = FALSE)
sys$path$append(path)
import("<module>")

That modification of the Python path could occur within your .onLoad() as well.

I was actually calling a custom defined function in a very lame way (by calling the whole python script). But, it will probably be the only python function and that's ok. I think a MWE is due.

I keep my py files in inst/py folder of my package. Let's call it my_fun.py.

import sys

def my_function():
  print("Hello dear.")

And then,

.onLoad <- function(libname, pkgname) {
  reticulate::source_python(system.file("py/my_fun.py",package="<mypackage>"),envir=globalenv())
}

Now, if the envir parameter stays as the default value parent.frame(), I cannot reach my_function. But if I set it to globalenv(), I can reach it.

My pedantery is to keep it in the package namespace. Though, my knowledge about the internals of R is limited at this scope.

Correct me if I'm wrong, but the functions you refer to import Python modules not custom functions. If source_python doesn't work. I am very new to reticulate and not a very amazing Python developer.

I'm in the same seat. The solution @berkorbay suggests above works, but it doesn't seem like it's the cleanest solution for those namespace reasons.

@berkorbay Try importing your script as a module with reticulate::import_from_path using the .onLoad method:

In ./R/zzz.R:

my_fun <- NULL

.onLoad <- function(libname, pkgname) {
the_module <- reticulate::import_from_path(module = "my_fun", path = system.file("py", package = packageName()))
my_fun <<- the_module$my_fun
}

Then export your function in your package NAMESPACE with export(my_fun)

Original Post here: https://community.rstudio.com/t/build-package-namespace-dynamically-during-onload/4101

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AnthonyEbert picture AnthonyEbert  路  8Comments

cb4github picture cb4github  路  5Comments

gadepallivs picture gadepallivs  路  8Comments

herboratory picture herboratory  路  6Comments

ruthkr picture ruthkr  路  5Comments