rexyai / RestRserve

R web API framework for building high-performance microservices and app backends
https://restrserve.org
276 stars 32 forks source link

Problem with reticulate #171

Closed cleytonfar closed 3 years ago

cleytonfar commented 3 years ago

First of all, I would like to thank the developers and contributors of RestRserve package. This package has been incredible useful to develop and deploy industry quality API with R.

Recently, I am having some trouble when I tried to deploy an API which uses user-defined python functions through the reticulate package. My first thought was this is a machine-specific problem, but I tested in two different computers and the same error appears. When I deploy the same program using plumber package, it works just fine. So I think this might be related to RestRServe.

The following code is a minimal reproducible example of the problem that I am facing. First, I save this add() function to a file called reprex.py:

def add(x, y):
  return x + y

The RestRserve code is as follows:

library(RestRserve)
library(reticulate)

# sourcing python function:
use_python("/usr/bin/python")
source_python("reprex.py")

## create app:
app <- Application$new(content_type = "application/json")

## add endpoint:
app$add_get(path = "/echo", FUN = function(request, response) {

    input <- request$body
    out = add(input[[1]], input[[2]])

    response$set_body(out)
    response$set_content_type("application/json")
})

## testing:
request <- Request$new(path = "/echo", 
                       method = "GET", 
                       body = '{"x": 10, "y": 3}', 
                       content_type = "application/json")

response <- app$process_request(request)
response$status
[1] "200 OK"
response$body
[1] "13"

When I test the application using Request, It works just fine. However, when I start the application the following error occurs:

## start application:
backend <- BackendRserve$new()
backend$start(app, http_port = 9080)
{"timestamp":"2020-10-27 11:07:13.258288","level":"INFO","name":"Application","pid":25890,"msg":"","context":{"http_port":9080,"endpoints":{"HEAD":"/echo","GET":"/echo"}}}
Error in py_get_item_impl(x, key, FALSE) : 
  RuntimeError: Evaluation error: object 'convert' not found.

Detailed traceback: 
  File "/home/cleyton/R/x86_64-pc-linux-gnu-library/4.0/reticulate/python/rpytools/call.py", line 21, in python_function
    raise RuntimeError(res[kErrorKey])
Calls: <Anonymous> ... py_get_attr_or_item -> py_get_item -> py_get_item_impl
Execution halted
dselivanov commented 3 years ago

If it works with 'process_request' but doesn't work when service is up then it means there is some issue on how reticulate initialise embedded python in a process fork. I haven't used reticulate with RestRserve myself, so not sure if they can interoperate nicely...

I will try to take a look in the coming days.

On Tue, 27 Oct 2020, 18:36 cleyton_farias, notifications@github.com wrote:

First of all, I would like to thank the developers and contributors of RestRserve package. This package has been incredible useful to develop and deploy industry quality API with R.

Recently I am having some trouble when I tried to deploy an API which uses user-defined python functions through the reticulate package. My first thought was this is a machine-specific problem, but I tested in two different computers and the same error appears. When I deploy the same program using plumber package, it works just fine. So I think this might be related to RestRServe.

The following code is a minimal reproducible example of the problem that I am facing. First, I save this add() function to a file called reprex.py:

def add(x, y): return x + y

The RestRserve code is as follows:

library(RestRserve) library(reticulate)

sourcing python function:

use_python("/usr/bin/python") source_python("reprex.py")

create app:app <- Application$new(content_type = "application/json")

add endpoint:app$add_get(path = "/echo", FUN = function(request, response) {

input <- request$body out = add(input[[1]], input[[2]])

response$set_body(out) response$set_content_type("application/json") })

testing:request <- Request$new(path = "/echo",

                 method = "GET",
                 body = '{"x": 10, "y": 3}',
                 content_type = "application/json")

response <- app$process_request(request)response$statusresponse$body

When I test the application using Request, It works just fine. However, when I start the application the following error occurs:

start application:backend <- BackendRserve$new()backend$start(app, http_port = 9080)

{"timestamp":"2020-10-27 11:07:13.258288","level":"INFO","name":"Application","pid":25890,"msg":"","context":{"http_port":9080,"endpoints":{"HEAD":"/echo","GET":"/echo"}}} Error in py_get_item_impl(x, key, FALSE) : RuntimeError: Evaluation error: object 'convert' not found.

Detailed traceback: File "/home/cleyton/R/x86_64-pc-linux-gnu-library/4.0/reticulate/python/rpytools/call.py", line 21, in python_function raise RuntimeError(res[kErrorKey]) Calls: ... py_get_attr_or_item -> py_get_item -> py_get_item_impl Execution halted

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rexyai/RestRserve/issues/171, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHC5XOQWNT4X4I7QSSV7BDSM3LIFANCNFSM4TA5MUCQ .

s-u commented 3 years ago

Python doesn't support fork if I recall, so I don't think you can use reticulate, but I haven't looked at it recently. If you need Python, you may be better off using a Python web service instead (you could put nginx in front to have different paths for Python and R API calls).

dselivanov commented 3 years ago

The issue seems related to #149 and the way we try to pre-compile environment. So @cleytonfar if you create BackendRserve with precompile = FALSE then reticulate should work seamlessly:

backend <- BackendRserve$new(precompile = FALSE)

For now I will switch precompile = FALSE as default value.