Running an R script that involves Packages from Python Code - python

So I'm currently working on a simple python code to run a simple R script. The R script is only about 6 lines but uses the package "pracma". Using the subprocesses module in python, It runs the script but with the typical "Error in library(pracma) : there is no package called 'pracma' ". I am just looking for a simple solution to be able to run R scripts that have non-base packages installed. I know you can somehow do this using rpy2, but I cannot get that to install using pip, and I'm also using Anaconda3.
All in all, I'd just like a simple package that runs R scripts that have packages installed in them. Any help would be greatly appreciated.
This is the relevant piece of my Python code:
sp.run('Rscript Hausdorff.R', shell=True)
bFile = open("HausdorffData/hausdorff.txt", "r")
result = bFile.read()
bFile.close()
hausdorff_dist = float(result)
return hausdorff_dist
This is my R script:
library(pracma)
setwd('HausdorffData')
PointsA <- as.matrix(read.table("HFileA.txt", header = FALSE))
PointsB <- as.matrix(read.table("HFileB.txt", header = FALSE))
H = hausdorff_dist(PointsA, PointsB)
write(H, file = "hausdorff.txt",ncolumns = 1, append = FALSE)
This produces the following error:
Error in library(pracma) : there is no package called 'pracma'
Execution halted

Thanks to #Dilettant for this:
Even when R can seemingly run the script individually without this, when running the R script from something like python, we need to make sure the script knows what path our library is in. This is achieved by adding this line to the start of the code:
.libPaths(dir\to\package)
If the code has any other lines involving changing working directory, those are unaffected by changing the library path.

Related

Problems with redirected stdin and stdout when using py in matlab to run python code

I have some python code that runs perfectly when run within python. When I run the code from within matlab using py I appear to have problems with the redirection of stdin and stdout.
The problem can be illustrated with the python code in a file ztest.py:
import os
def ztest():
os.system(f'./jonesgrid > /dev/null < zxcvbn-split-08.txt')
When run within python, all is well:
>>> import ztest
>>> ztest.ztest()
>>>
When this is run from matlab with the command
>> py.ztest.ztest()
I get the following output:
At line 283 of file jonesgrid.for (unit = 5, file = 'fort.5')
Fortran runtime error: End of file
Error termination. Backtrace:
#0 0x2aaaaacead1a
<other lines cut>
The file fort.5 has been created together with fort.6. Normally these two files are associated with standard input and output respectively and are not created in the run. I have also tried using subprocess.run() and get the same problem.
I'm not sure whether this should be posted in a python forum or a matlab one, but I'm guessing the problem lies with the way in which matlab is interfacing with python. Other parts of my code that use os.system() that don't make use of redirection work fine.

Can't complete Cron Job when python code is embed (through reticulate) inside the R script

I've created an R script that first launches a python script through the py_run_file() function and then executes some R code. I need to schedule the launch of such script at a certain hour of the day, and hence I used the package cronR. Unfortunately, when I call the script function just as a cron job, the job freezes and doesn't end. Here's a reproducible example:
library(reticulate)
today <- Sys.Date()
use_python("~/miniconda3/bin/python3.8",
required = TRUE)
py_run_file("~/Desktop/test.py")
print(paste("End on the",
today))
This is the content of the test.py file:
print("python script!")
Do you have any suggestion? Thanks a lot for your help!
for some odd reason, whenever you run an R Cron Job using reticulate package, I figured after a lot of trial and error, we have to use it like this :
reticulate::use_python(python = '/usr/bin/python3', required = T)
reticulate::source_python("FULL_PATH_TO_PYTHON_FILE.py")
instead of importing the library using library(reticulate) this thing strangely works!

What does it mean to "initialize the Julia runtime" when exporting compiled .dll or .so files for use in other langauges?

I'm trying to compile a usable .dll file from Julia to be used in Python as I've already written a large GUI in Python and need some fast optimization work done. Normally I would just call PyJulia or some "live" call, however this program needs to be compiled to distribute within my research team, so whatever solution I end up with needs to be able to run on its own (without Julia or Python actually installed).
Right now I'm able to create .dll files via PackageCompiler.jl, something I learned from previous posts on StackOverflow, however when trying to run these files in Python via the following code
Julia mock package
module JuliaFunctions
# Pkg.add("BlackBoxOptim")
Base.#ccallable function my_main_function(x::Cfloat,y::Cfloat)::Cfloat
z = 0
for i in 1:x
z += i ^ y
end
return z
end
# function julia_main()
# print("Hello from a compiled executable!")
# end
export my_main_function
end # module
Julia script to use PackageCompiler
# using PackageCompiler
using Pkg
# Pkg.develop(path="JuliaFunctions") # This is how you add a local package
# include("JuliaFunctions/src/JuliaFunctions.jl") # this is how you add a local module
using PackageCompiler
# Pkg.add(path="JuliaFunctions")
#time create_sysimage(:JuliaFunctions, sysimage_path="JuliaFunctions.dll")
Trying to use the resulting .dll in CTypes in Python
import ctypes
from ctypes.util import find_library
from ctypes import *
path = os.path.dirname(os.path.realpath(__file__)) + '\\JuliaFunctions.dll'
# _lib = cdll.LoadLibrary(ctypes.util.find_library(path)) # same error
# hllDll = ctypes.WinDLL(path, winmode=0) # same error
with os.add_dll_directory(os.path.dirname(os.path.realpath(__file__))):
_lib = ctypes.CDLL(path, winmode=0)
I get
OSError: [WinError 127] The specified procedure could not be found
With my current understanding, this means that CTypes found the dll and imported it, but didn't find.. something? I've yet to fully grasp how this behaves.
I've verified the function my_main_function is exported in the .dll file via Nirsoft's DLL Export Viewer. Users from previous similar issues have noted that this sysimage is already callable and should work, but they always add at the end something along the lines of "Note that you will also in general need to initialize the Julia runtime."
What does this mean? Is this even something that can be done independently from the Julia installation? The dev docs in PackageCompiler mention this, however they just mention that julia_main is automatically included in the .dll file and gets called as a sort of launch point. This function is also being exported correctly into the .dll file the above code creates. Below is an image of the Nirsoft export viewer output for reference.
Edit 1
Inexplicably, I've rebuilt this .dll on another machine and made progress. Now, the dll is imported correctly. I'm not sure yet why this worked on a fresh Julia install + Python venv, but I'm going to reinstall them on the other one and update this if anything changes. For anyone encountering this, also note you need to specify the expected output, whatever it may be. In my case this is done by adding (after the import):
_lib.testmethod1.restype = c_double # switched from Cfloat earlier, a lot has changed.
_lib.testmethod1.argtypes = [c_double, c_double] # (defined by ctypes)
The current error is now OSError: exception: access violation writing 0x0000000000000024 when trying to actually use the function, which is specific to Python. Any help on this would also be appreciated.

How to run python from C# without .exe file

I am a Python beginner and wrote some Python code that I want to run from my C# code.
In all the answers I have seen already, the way was to make a .exe file from the .py one and run it by system call.
However, I want it so that I do not need to make the .exe file and can write the commands with arguments as I could in the command line.
C:\Users\ntuser> python C:\Users\ntuser\Documents\run_python.py 3
Is there a way to do it?
I found a way to pass just one command—but I need to make two: 1. Go to "C:\Users\ntuser" 2. Run the Python code.
Thanks!
OK, so I found a solution.
Thanks to UnholySheep for the help.
What you need to do is:
Make the python as system variable
Go by code to your home directory:
Directory.SetCurrentDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
Add this code for calling the python code:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;//if you want to hide the window
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C python pytonPath\\python_code.py";
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();//if you want to wait

Extend the functionality of a compiled Python script

I'm not a programmer, so I don't even know in what terms should I ask this. Let's say I've compiled a Python script to have an .exe (I use py2exe to do this). This is the major program. Now, I want to add some extra functionality to it, but I don't want to recompile the entire script with the added functionality. I tried to search something on the web, and I found examples of extending a C++ or other application with Python scripts (like a sort of plugin). But I can't figure out how to do it with an application already written in Python.
I tried this: I wrote major.py (this is the script from where I build the executable) and stuff.py. In major I wrote this:
def generic():
import stuff
while True:
param=input('what did you say? ')
stuff.speak(param)
generic()
And in stuff I wrote this:
def speak(param):
print(param)
Then I created a .exe with py2exe. It works as expected, when I run the program in the command line says "what did you say?" and waits until I type something, then it prints what I typed.
Then, I changed stuff.py with this:
def speak(param):
print('I said '+param)
Hoping that now upon the execution of the .exe created earlier it would print "I said.." plus whatever I typed. Obviously, it didn't work, the program continued to behave like before. So I'm guessing that once I imported stuff and created the .exe file, that import is permanent, not allowing me to change whatever is in stuff. What should I do?
py2exe packs the compiled scripts in the executable.
You need to recreate the executable (which will recompile any changed script) to see the changes take effect.
EDIT following the comments:
You can do it if you dynamically import/reimport the module from inside the executable.
In your main script you do (see code below)
mod, error = loadmodule('mystuff.py')
if mod is not None:
# loading succeeded you can now proceed and do things with it
pass
Of course you have to leave mystuff.py out of the scripts that py2exe packs into the executable. In the above example mystuff.py would be in the same directory as the executable.
The loading code:
def loadmodule(modpath, modname=''):
if not modpath.endswith('.py'):
modpath += '.py'
# generate a random name for the module
if not modname:
modpathbase = os.path.basename(modpath)
modname, _ = os.path.splitext(modpathbase)
version = (sys.version_info[0], sys.version_info[1])
if version < (3, 3):
mod, e = loadmodule2(modpath, modname)
else:
mod, e = loadmodule3(modpath, modname)
return mod, e
def loadmodule2(modpath, modname):
import imp
try:
mod = imp.load_source(modname, modpath)
except Exception as e:
return (None, e)
return (mod, None)
def loadmodule3(modpath, modname):
import importlib.machinery
try:
loader = importlib.machinery.SourceFileLoader(modname, modpath)
mod = loader.load_module()
except Exception as e:
return (None, e)
return (mod, None)
If you run your script from Python, instead of compiling it as an executable, you can make changes and run them without having to recompile. The py2exe is mostly for allowing you to distribute your application to other Windows computers that don't have Python installed. After you have finished developing it, then compile it as an executable so you can run it on other computers.
There is no way to do what you want. py2exe builds a standalone python interpreter (In the file named python.dll) with just the dependencies of your project. Then the .exe file runs your script using that interpreter
I suggest you that if you really need to provide regular upgrades then you should recompile it, or install python in the target machine, or make an updating routine that checks for updates and compiles it in the target machine (With py2exe)

Categories

Resources