Run Python with imports via java ScriptEngineManager - python

Similar question have been asked here an year ago but no answer yet.
Im running a Python script via Java and I'm getting
ImportError: No module named numpy in <script> at line number 1
This is my code:
public void runScript(String filePath) throws Exception {
StringWriter writer = new StringWriter();
ScriptContext context = new SimpleScriptContext();
context.setWriter(writer);
Options.importSite = false;
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");
engine.eval(new FileReader(filePath), context);
System.out.println(writer);
}
How do I run script with it's imports?
Of course all the required installations have been installed (with pip install) and that the code runs perfectly when I run it not through java.

Related

Run Python app (script on PATH) from Java

I'm facing quite simple problem, yet still not able to figure out what in particular causes that, and - more importantly - how to solve it.
I'm currently on Linux, and I would like to run an python app (script) from a Java application. The script is on PATH, thus I really would like to utilise that (avoid using absolute path to the script), if possible.
However, all I tried resulted in various forms of "File does not exist".
Sample
As a demonstration, I've tried to run one python3-based app (meld)
and one binary-built app (ls) for comparison:
$ which ls
/usr/bin/ls
$ file /usr/bin/ls
/usr/bin/ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=[...], for GNU/Linux 3.2.0, stripped
$ which meld
/usr/bin/meld
$ file /usr/bin/meld
/usr/bin/meld: Python script, UTF-8 Unicode text executable
$ head -n1 /usr/bin/meld
#!/usr/bin/python3
Nextly, I've created simple Java main, which tries several ways how to start theese:
package cz.martlin.processes;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.List;
import java.util.stream.Collectors;
public class ProcessPlaying {
public static void main(String[] args) {
List<List<String>> commands = List.of(
List.of("ls"),
List.of("/usr/bin/ls"),
List.of("meld"),
List.of("/usr/bin/meld"),
List.of("python3", "/usr/bin/meld"),
List.of("/usr/bin/python3", "/usr/bin/meld"),
List.of("sh", "-c", "meld"),
List.of("sh", "-c", "/usr/bin/meld"),
List.of("sh", "-c", "python3 /usr/bin/meld")
);
for (List<String> command : commands) {
run(command);
}
}
private static void run(List<String> command) {
System.out.println("Running: " + command);
//String executable = command.get(0);
//boolean exists = new File(executable).exists();
//System.out.println("Exists the " + executable + " ? " + exists);
try {
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectError(Redirect.INHERIT);
Process proc = pb.start();
// Process proc = Runtime.getRuntime().exec(command.stream().collect(Collectors.joining(" ")));
int code = proc.waitFor();
System.out.println("OK, return code: " + code);
} catch (IOException e) {
System.out.println("Failed to start: " + e.toString());
} catch (InterruptedException e) {
System.out.println("Failed to await: " + e.toString());
}
System.out.println();
}
}
Here are the results:
Running: [ls]
OK, return code: 0
Running: [/usr/bin/ls]
OK, return code: 0
Running: [meld]
Failed to start: java.io.IOException: Cannot run program "meld": error=2, Directory or file doesn't exist
Running: [/usr/bin/meld]
Failed to start: java.io.IOException: Cannot run program "/usr/bin/meld": error=2, Directory or file doesn't exist
Running: [python3, /usr/bin/meld]
python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
Running: [/usr/bin/python3, /usr/bin/meld]
/usr/bin/python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
Running: [sh, -c, meld]
sh: line 1: meld: command not found
OK, return code: 127
Running: [sh, -c, /usr/bin/meld]
sh: line 1: /usr/bin/meld: Directory or file doesn't exist
OK, return code: 127
Running: [sh, -c, python3 /usr/bin/meld]
python3: can't open file '/usr/bin/meld': [Errno 2] No such file or directory
OK, return code: 2
To sum it up:
all of the commands tried works when executed directly from the shell (either sh or bash)
executing the binary works either by the full path (/usr/bin/ls) or by just the name (ls)
executing the python script the same way doesn't work neither way
when trying to run the python3 interpreter and populate the script path as an argument to the python, now the python yields the script file doesn't exist
trying to populate it as a command to the brand new shell didn't help either
I've tried to use the Runtime#exec (based on this comment: https://stackoverflow.com/a/36783743/3797793) to start the process (both the exec(String) and exec(String[] forms), but no sucess (none of the listed commands did actually execute).
Thus, my question is/are:
What do I understand wrong?
How to start the Python script from Java?
Would some small (ba)sh script wrapper do the job?
Since it's python3-based, Jython wouldn't help here (because the latest one is 2.7.*), would it?
Further requirements:
As mentioned, I would like to be able to avoid using full path to the Python script
Also, I would like to have platform independant solution (at least Linux and Windows compatible)
Thanks in advance

Python module not found in Nix-generated Python environment

I need my user environment configured with Python and the beancount module available. The way I'm currently doing this is to add this package to home.packages (I am using home-manager):
(python310.withPackages (_: [ python310Packages.beancount ]))
This gives me Python 3.10, but upon trying import beancount, I get a ModuleNotFoundError.
The reason I'm invoking withPackages in this way, and not with (python-packages: with python-packages; [ beancount ]) is because I am overriding the beancount module. I am on an Apple Silicon system and am having issues building beancount on aarch64-darwin, so I simply use the x86_64-darwin version, which works fine. This is done with the following two overlays:
(final: prev: (optionalAttrs (prev.stdenv.system == "aarch64-darwin") {
pkgs-x86 = import nixpkgs-unstable {
system = "x86_64-darwin";
inherit (nixpkgsConfig) config;
};
}))
(final: prev: (optionalAttrs (prev.stdenv.system == "aarch64-darwin") {
python310Packages.beancount = final.pkgs-x86.python310Packages.beancount;
}))
My suspicion is that the way I'm invoking withPackages is the reason the package is not added to Python's environment, but I'm not sure if this is the case. Either way, how would I go about fixing the issue?
I read somewhere that withPackages fetches packages from PyPi. Is there a way to force x86_64-darwin to be used here? Alternatively, is there a way to manually add modules to Nix's Python environment?
Please take a look at https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md#overriding-python-packages-overriding-python-packages on how to overwrite python packages.
Example overlay from my that I used a while back:
final: prev: {
python3 = prev.python3.override {
packageOverrides = final: prev: {
python-swiftclient = prev.python-swiftclient.overrideAttrs (oldAttrs: rec {
postInstall = ''
install -Dm644 tools/swift.bash_completion $out/share/bash_completion.d/swift
'';
});
};
};
}

call python script in java application (Error in python import)

I call my python script with java and also pass variables. My The script alone in a PyCharm project works so far, only if I call it via Java (InteliJ) nothing happens.
The program should pass values ​​to my script via Java so that the script changes and saves values ​​in a Word Document (docx).
If I use the version of my script in the Intelij folder, it has problems importing docx.
I think the problem is that in the PyCharm project the docx data is directly in the project. This is not the case with Intelij and it should access the system data from docx.
I have already completely reinstalled lxml and docx but to no avail.
How do I have to change my program structure or my script so that it works.
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class runPython {
public static void main(String[] args) throws IOException {
try {
ProcessBuilder builder = new ProcessBuilder("python", "C://Users//Notebook//IdeaProjects//bhTool_bridge//scripts//main.py", "Annemarie Brekow");
Process process = builder.start();
}
catch (Exception e){
e.printStackTrace();
}
}
}
Python:
from docx import Document
import sys
import os
document = Document('C:/Users/Notebook/IdeaProjects/bhTool_bridge/template/Muster_Rechnung.docx')
workingdirectory=os.getcwd()
def find_replace(paragraph_keyword, draft_keyword, paragraph):
if paragraph_keyword in paragraph.text:
# print("found")
paragraph.text = paragraph.text.replace(paragraph_keyword, draft_keyword)
for paragraph in document.paragraphs:
find_replace("$Kunden-Name", "Annemarie Brekow", paragraph)
print(paragraph.text)
document.save("C:/Users/Notebook/IdeaProjects/bhTool_bridge/template/Muster_Rechnung.docx")
EDIT:
Errormsg
Traceback (most recent call last):
File "C:\Users\Notebook\IdeaProjects\bhTool_bridge\scripts\main.py", line 2, in
from docx import Document
ModuleNotFoundError: No module named 'docx'

How to bundle python code with vsix (vscode extension)

I am creating a vscode extension where I need machine learning tasks to be performed. I have python files that have code that is required in vscode extension. I don't want things to be done using request-response on any python server. What I want is to perform the ML tasks on device (integrated with the vsix).
We have child-process available in js to run basic python file using spawn. It is running fine on both, extension host window and external vscode editor after packaging, with the python code that has basic imports like import sys. But if I try to import some other libraries like numpy, pygments, it is working only on extension host environment, not on other vs window after packaging it. How can I run the typical python code with the vsix?
Below are both the codes that is working fine and not working at all-
TS file (MLOps.ts)-
import { ChildProcessWithoutNullStreams, spawn } from "child_process";
import { join } from "path";
import * as vscode from 'vscode'
export async function pythonOps(): Promise<string> {
var result = "testt"
var promise = await new Promise((resolve, reject) => {
var p = __dirname.split('\\')
p.pop()
var path = p.join('\\')
var pyPath = join(path, 'src', 'py_operations.py')
var result = "blank result"
var arg1 = "arg one"
var arg2 = "arg two"
var py_process = spawn('python', [pyPath, arg1, arg2])
py_process.stdout.on('data', (data: any) => {
vscode.window.showInformationMessage(data.toString())
result = data.toString()
})
})
}
Working Python code (py_operations.py)- This code is working on both, on extension host window and after packaging the extension and installing the vsix on other system.
import sys
print("Some text with: ",sys.argv[0], sys.argv[1], sys.argv[2])
sys.stdout.flush()
Not working Python code- This code is working only on extension host window, and not working after packaging this and isntalling on other system.
import sys
from pygments.lexers.javascript import TypeScriptLexer
lexer = TypeScriptLexer()
src = "alert('text here')"
lexer_tokens = lexer.get_tokens(src)
l = []
for t in lexer_tokens:
l.append(t[1])
print("list: ",l)
sys.stdout.flush()
How can I run the second python code with packaged vsix?

Permission denied when trying to execute python process from DotNet Core MVC project

I've created a DotNet Core Razor MVC project and in there, I have created a directory called python. Within that python directory, I have created a python script called myscript.py.
Following the real-time chat example for SignalR, I have added a function to my ChatHub which is supposed to execute myscript.py:
private string ProcessMessage(string message)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "/Users/SomeUser/Documents/Code/VisualStudio/MyProject/MyProject/python/myscript.py";
start.Arguments = message;
start.UseShellExecute = false;// Do not use OS shell
start.CreateNoWindow = true; // We don't need new window
start.RedirectStandardOutput = true;// Any output, generated by application will be redirected back
start.RedirectStandardError = true; // Any error in standard output will be redirected back (for example exceptions)
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string stderr = process.StandardError.ReadToEnd(); // Here are the exceptions from our Python script
string result = reader.ReadToEnd(); // Here is the result of StdOut(for example: print "test")
return result;
}
}
}
Notice I have provided the full path to start.FileName. However, when I run this, I get a permission denied error.
I've tried various combinations of that path (e.g. ~/python/myscript.py)
How can I resolve this? I'm running VS for Mac, if that makes a difference.

Categories