I have an Azure Function that executes R code by using RDotNet library (R.Net)
Everything works fine on my local environment, but when I deploy my code to azure, the process to load specific libraries (zoo, TTR) never ends.
This is my code:
string rHome = #"D:\home\site\wwwroot\R\R-3.4.4";
string rPath = Path.Combine(rHome, System.Environment.Is64BitProcess ?
#"bin\x64" : #"bin\i386");
REngine.SetEnvironmentVariables(rPath, rHome);
if (engine == null)
{
engine = REngine.GetInstance();
}
engine.Evaluate(#"library(data.table)");
engine.Evaluate(#"library(RODBC)");
engine.Evaluate(#"library(nlstools)");
engine.Evaluate(#"library(minpack.lm)");
engine.Evaluate(#"library(zoo)");
engine.Evaluate(#"library(TTR)");
The first 4 libraries are loaded without any problem, but when the program tries to load zoo library this process never ends and I cannot continue executing the rest of my code.
No error is displayed so the Azure Function is restarted after some minutes.
Same thing happens with library TTR
Any idea on what could be the cause of these symptoms?
Related
I wanted to make internally sharing/locally launching a shiny app developed with the {golem} framework a little more robust.
Hence, I used the renv package and installed the shiny app as a local package into a project folder.
I proceeded as follows (thanks #Kat for the suggestion):
initialize renv using renv::init(bare = TRUE)
renv::install("my_local_package")
renv::snapshot(type = "all")
renv::isolate()
Writing a launch file consisting of:
library(golempackage)
renv::restore()
golempackage::run_app(options = list(launch.browser = TRUE))
Share folder.
However, when launching the shiny app on a different computer (or a docker testing environment), I get the following error caused by the package bslib. Same happens when I delete my cache:
An error has occurred!
File attachments must exist: 'C:/Users/XYZ/AppData/Local/R/cache/R/renv/cache/v5/.../bslib/lib/bs3/assets/fonts'
Note: this error even occurs if I set the cache to be project-local and share it inside the project folder.
However, now the error message does not reference the global but the project-local cache. Unfortunately still as an absolute path which throws an error for other users.
This is all super weird and I have not the slightest idea why this occurs.
I would like to avoid removing bslib.
As far as I can see, the error is coming from the sass package, e.g.
https://github.com/rstudio/sass/blob/f7a954027447dd0b9826ec01c7084c89a6e64fcc/R/layers.R#L442-L443
While I don't know exactly know what's going on, you could probably use the R debugger to check why that's failing. (Does the referenced folder exist in both cases? Are you expecting renv to be using the cache in the second case?)
Context
I'm developing (for the first time) an R package using Rcpp which implements an interface to another program (maxima). This package defines a C++ class, whose constructor needs to retrieve the path to an initialization script that gets installed with the package (the in-package path is inst/extdata/maxima-init.mac. The path to this script is then used as a parameter to spawn a child process that runs the program.
In order to retrieve the path to the installed initialization script I'm calling the R function base::system.file from within the C++ class constructor definition:
...
Environment env("package:base");
Function f = env["system.file"];
fs::path p(Rcpp::as<std::string>(f("extdata", "maxima-init.mac", Named("package") = "rmaxima")));
std::string utilsDir = p.parent_path().string();
...
# spawn child process using path in utilsDir
My R/zzz.R creates an object of that class when the packages gets attached:
loadModule("Maxima", TRUE)
.onAttach <- function(libname, pkgname) {
"package:base" %in% search()
maxima <<- new(RMaxima)
}
The Problem
I can install.packages(rmaxima) and library(rmaxima) just fine and the package works as expected.
I now want to increase my development efficiency by using devtools::load_all() to avoid having to R CMD build rmaxima, install.packages(rmaxima) and library(rmaxima) each time I want to test changes. However, when calling devtools::load_all() (or similarily devtools::test() (working directory set to package root) my implementation freezes, because the variable utilsDir is empty and therefore the process launching does not return (I guess it keeps waiting for a valid path). I eventually need to manually kill the process. The same thing happens without setting .onAttach()
Apparently devtools::load_all() does not resemble R's default search path on restart. What can I do? Is this the problem or am I missing something else?
Update
I just came across the following notion of in the devtools::load_all() R documentation file which could be a tip in the right direction
Shim files:
‘load_all’ also inserts shim functions into the imports environment of
the loaded package. It presently adds a replacement version of
‘system.file’ which returns different paths from ‘base::system.file’.
This is needed because installed and uninstalled package sources have
different directory structures. Note that this is not a perfect
replacement for base::system.file.
Also I realized, that devtools::load_all() only temporarily installs my package into, but somehow doesn't the files from my inst/
rcst#Velveeta:~$ ls -1R /tmp/RtmpdnvOQg/devtools_install_ee1e82c780/rmaxima/
/tmp/RtmpdnvOQg/devtools_install_ee1e82c780/rmaxima/:
DESCRIPTION
libs
Meta
NAMESPACE
/tmp/RtmpdnvOQg/devtools_install_ee1e82c780/rmaxima/libs:
rmaxima.so
/tmp/RtmpdnvOQg/devtools_install_ee1e82c780/rmaxima/Meta:
features.rds
package.rds
As it turns out devtools provides a solution to exactly this problem.
In short: calling system.file (i.e. from the global environitment and having the devtools package attached) solves the issue. Specifically the modification:
// Environment env("package:base");
// Function f = env["system.file"];
Function f("system.file");
fs::path p(Rcpp::as<std::string>(f("extdata", "maxima-init.mac", Named("package") = "rmaxima")));
std::string utilsDir = p.parent_path().string();
Explanation
base::system.file(..., mustWork = FALSE) returns an empty string if no match is found. devtools::load_all() temporarily installs the packages inside /tmp/ (on my linux machine). The directory structure of the temporary installation differs from the one of the regular installation, i.e. the one created by install.packages(). In my case, most notably, devtools::load_all() does not copy the inst/ directory, which contains the initialization file.
Now, calling base::system.file("maxima-init.mac", package="rmaxima", mustWork=FALSE) naturally fails, since it searches inside the temporary installation. Having devtools attached masks system.file() with devtools::system.file(), which as mentioned above is "... meant to intercept calls to base::sysem.file() " and behaves differently from base::system.file(). Practically, I think this means, that it will search for the package's source directory instead of the temporary installation.
This way, simply calling system.file() from the global environment calls the right function, either from devtools or base, for either the development or user version of the package automatically.
Nonetheless, using ccache additionally (thanks #dirk) substantially speeds up my development workflow.
I'm trying to setup a simple beakr service in Windows that implements the example at https://github.com/MazamaScience/beakr. I'm able to run the script from the command line successfully and I've been able to add the service in Windows using NSSM, but I am unable to start the service.
When I dig into the service error logs I see that Rscript.exe cannot be executed due to a non-specific permissions problem.
My Rscript.exe is running out of C:\Program Files\R<Version>\bin and my beakr.R script is running out of my User home directory.
If anyone has had success implementing a similar service (Web page based REST endpoint) using R in Windows, I would love to know how you did it.
This is what I did to run an R script as Service using latest pre-release version of NSSM on Windows 10:
Create a directory to store the files
In this example : C:\R\ServiceTest
Create in this directory a never ending script : ServiceTest.R
library(beepr)
# Test script : beeps every 10 seconds
while (T) {
beepr::beep(1)
if (interactive()) {
# Shows spin cursor to facilitate test in interactive mode
for (i in 1:10) {
if (i%%4==0) {cursor <- '/'}
if (i%%4==1) {cursor <- '-'}
if (i%%4==2) {cursor <- '\\'}
if (i%%4==3) {cursor <- '|'}
cat('\r',cursor)
flush.console()
Sys.sleep(1)
}
} else {
Sys.sleep(10)
}
}
I used to let this kind of script run in a console open on my desktop to check various alarms regularly.
Create a batch file to run the script : ServiceTest.bat
Rscript ServiceTest.R
Open an Admin console and make sure the batch file runs correctly:
C:\R\ServiceTest>ServiceTest.bat
C:\R\ServiceTest>Rscript ServiceTest.R
|
Cancel the batch (Ctrl+C)
Using the Admin console, install the batch file as service using NSSM :
nssm install
Set Service name : ServiceTest
Set Application path : C:\R\ServiceTest\ServiceTest.bat
Set Working directory : C:\R\ServiceTest\
Set Logon : Windows User + Password
Install Service
Open Windows Services Manager, find ServiceTest and start it : if everything went well, that's it!
If you get an error message, check Windows Event Log / Services : you can find there hints on the cause of the problem. Most common problems I encountered :
error on path
used local user instead of own user account / password to run the service
If you want to remove the service :
nssm remove ServiceTest
This replaced very nicely the many R consoles I left running in the background on my Desktop.
I see no reasons it wouldn't work with a REST endpoint.
I'm using the package RSAP to read SAP data.
RSAP loads a SNC (Secure Network Connection) dynamic library and searching for it with the environment variable SNC_LIB.
Depending on the local user system, this might be a 32 or 64 bit library.
I'm setting the environment variable within my R script.
But RSAP still search in the old path.
I try to avoid setting the environment variable outside by application because it's a shiny app which should be used by many users.
It seems that the environment variable is changed only within the RSTUDIO session but not outside.
Initial situation of the environment variables within RStudio console:
> Sys.getenv("SNC_LIB_64")
[1] "C:\\Program Files\\SAP\\FrontEnd\\SecureLogin\\lib\\sapcrypto.dll"
> Sys.getenv("SNC_LIB")
[1] "C:\\Program Files (x86)\\SAP\\FrontEnd\\SecureLogin\\lib\\sapcrypto.dll"
Coding:
# check SNC_LIB path from environment variables
# 32 or 64 bit?
# if 64 bit lib path is set, set the default lib path variable
# SNC_LIB to it
lib_path_64 <- Sys.getenv("SNC_LIB_64")
if (lib_path_64 != "") {
Sys.setenv("SNC_LIB" = lib_path_64)
}
After the code is executed in RStudio debugger:
Browse[2]> Sys.getenv("SNC_LIB")
[1] "C:\\Program Files\\SAP\\FrontEnd\\SecureLogin\\lib\\sapcrypto.dll"
Error thrown by RSAP on loading the library:
[Thr 12160] Wed Jan 03 17:42:57 2018
[Thr 12160] *** ERROR => SncPDLInit()==SNCERR_INIT, Adapter #1 (C:\Program Files (x86)\SAP\FrontEnd\SecureLogin\lib\sapcrypto.dll) not loaded [sncxxdl.c 727]
Old path is used. When I change the path outside before running RStudio it's working.
Question:
Is there a way to set the library path variable SNC_LIB in another way to be sure is globally and not locally changed and RSAP dynamic loading is working well?
Easy way to reproduce is:
Start RStudio
Call Sys.setenv("TEST_VAR" = "good")
Call Sys.getenv("TEST_VAR")
See right result [1] "good"
Close RStudio
Start RStudio again
Call again Sys.getenv("TEST_VAR")
See 'wrong' unexpected result [1] ""
Environment variables set in R affect that process and processes it runs, they don't persist when R quits.
It's not clear what steps you took to lead to your RSAP error, but your "easy code to reproduce" script is acting as expected.
The only way a Sys.setenv() in an R session will affect a subsequent library load is if that load is happening in the R session (e.g. loading an R package that loads the library) or in a process R launches (e.g. running a command using system()).
This is the first time I have tried to connect R and Tableau.
I have downloaded and installed Rserve successfully but every time I try to start Rserve is get this warning:
Starting Rserve...
"C:\Users\SIMON~1.HAR\DOCUME~1\R\WIN-LI~1\3.1\Rserve\libs\x64\Rserve.exe"
Warning message:
running command '"C:\Users\SIMON~1.HAR\DOCUME~1\R\WIN-LI~1\3.1\Rserve\libs\x64\Rserve.exe" ' had status 127
I have been searching for days and couldn't find any fix.
The Rserve() function is trying to start an application (Rserve.exe) and failed. There's a couple of things you can do.
Go to the "C:\Users\SIMON~1.HAR\DOCUME~1\R\WIN-LI~1\3.1\Rserve\libs\x64\" file directory and try loading the exe yourself, troubleshoot from there.
use the run.Rserve() function instead of Rserve(). This will use your current R session to start the Rserve server. This means the exe doesn't need to be run. This worked well for me because I am working in an environment where I don't enough privileges to run the exe. It does mean that your R session can't do anything else while the server is running, but you can always load up 2 sessions at the same time.