I have a simple Java app that does an addition by passing 2 arguments when running it. Here is the code:
package test_python;
import java.util.concurrent.TimeUnit;
public class Test_python {
public int addition(int first, int second) {
return first + second;
}
public static void main(String[] args) {
Test_python a = new Test_python();
System.out.println(a.addition(Integer.parseInt(args[0]), Integer.parseInt(args[1])));
}
}
And I have a python script :
import subprocess
import sys
first_arg = subprocess.check_output([sys.argv])
second_arg = subprocess.check_output([sys.argv])
subprocess.call(['java', '-jar', 'test_python.jar ',first_arg,second_arg])
I would like to pass two arguments like 2 and 3 to the python script and the to send the arguments to the jar and return the response. I get this error when I try:
Traceback (most recent call last):
File "C:\Certificat python\start-stop.py", line 5, in <module>
first_arg = subprocess.check_output([sys.argv])
File "C:\Users\40723\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line
424, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "C:\Users\40723\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line
505, in run
with Popen(*popenargs, **kwargs) as process:
File "C:\Users\40723\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line
951, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:\Users\40723\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line
1360, in _execute_child
args = list2cmdline(args)
File "C:\Users\40723\AppData\Local\Programs\Python\Python39\lib\subprocess.py", line
565, in list2cmdline
for arg in map(os.fsdecode, seq):
File "C:\Users\40723\AppData\Local\Programs\Python\Python39\lib\os.py", line 822, in
fsdecode
filename = fspath(filename) # Does type-checking of `filename`.
TypeError: expected str, bytes or os.PathLike object, not list
Can you please give me a solution ?
Thanks in advance
The cause of the error is because sys.argv is already a list e.g. ["script.py", "2", "3"] and you are wrapping it in another list thus making it [["script.py", "2", "3"]].
first_arg = subprocess.check_output([sys.argv])
Removing the outer list-wrapper and also removing the first item which is the script itself would remove the error.
first_arg = subprocess.check_output(sys.argv[1:])
But I doubt that is what you need, because subprocess.check_output runs the command, it doesn't get the arguments as what you are trying to do.
$ python script.py cat script.py # <cat> is a linux command that prints the file
b'#!/usr/bin/env python\n\nimport subprocess\nimport sys\n\n\nresult = subprocess.check_output(sys.argv[1:])\nprint(result)\n'
If what you want is to just get the values of the first and second argument e.g. 2 and 3 if invoked as python script.py 2 3, you can just do:
first_arg = sys.argv[1]
second_arg = sys.argv[2]
Related
We write our jenkins pipeline using groovy script. Is there any way to identify the folder size or file size.
Our goal is to identify size of two zip files and calculate the difference between them.
I tried below code but its not working.
stage('Calculate Opatch size')
{
def sampleDir = new File('${BuildPathPublishRoot}')
def sampleDirSize = sampleDir.directorySize()
echo sampleDirSize
}
Getting below error :-
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.io.File.directorySize() is applicable for argument types: () values: []
Possible solutions: directorySize()
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:154)
Here's what worked for me. Grab all the files in a directory and sum the lengths.
Please note that you'll need to use quotes (") in order for string interpolation to work, i.e. "${BuildPathPublishRoot}" places the value of the BuildPathPublishRoot variable into the string, whereas '${BuildPathPublishRoot}' is taken literally to be the directory name.
workspaceSize = directorySize("${BuildPathPublishRoot}")
/** Computes bytes in the directory*/
public def directorySize(directory){
long bytes = 0
directory = (directory?:'').replace('\\','/')
directory = (directory =='') ? '' : (directory.endsWith('/') ? directory : "${directory}/")
def files=findFiles(glob: "${directory}*.*")
for (file in files) {
if (!file.isDirectory()){
bytes += file.length
}
}
return bytes
}
I am using the sklearn-weka-plugin and want to run the JRip classifier. When I try to run it with the python-weka-wrapper:
import weka.core.jvm as jvm
from weka.classifiers import Classifier
jvm.start()
jrip = Classifier("weka.classifiers.rules.JRip")
jvm.stop()
everything works fine, but if I try to do the same with the sklearn-weka-plugin:
import sklweka.jvm as jvm
from sklweka.classifiers import WekaEstimator
jvm.start()
jrip = WekaEstimator("weka.classifiers.rules.JRip")
jvm.stop()
I get the following error message:
Failed to get class weka.classifiers.rules.JRip
Exception in thread "Thread-0" java.lang.NoClassDefFoundError: weka.classifiers.rules.JRip
Traceback (most recent call last):
File "sklearn_weka_test.py", line 21, in <module>
jrip = WekaEstimator("weka.classifiers.rules.JRip")
File "/home/andreas/.local/lib/python3.8/site-packages/sklweka/classifiers.py", line 45, in __init__
if not is_instance_of(_jobject, "weka.classifiers.Classifier"):
File "/home/andreas/.local/lib/python3.8/site-packages/weka/core/classes.py", line 285, in is_instance_of
if is_array(obj):
File "/home/andreas/.local/lib/python3.8/site-packages/weka/core/classes.py", line 309, in is_array
cls = javabridge.call(obj, "getClass", "()Ljava/lang/Class;")
File "/home/andreas/.local/lib/python3.8/site-packages/javabridge/jutil.py", line 888, in call
fn = make_call(o, method_name, sig)
File "/home/andreas/.local/lib/python3.8/site-packages/javabridge/jutil.py", line 846, in make_call
raise JavaException(jexception)
javabridge.jutil.JavaException: weka.classifiers.rules.JRip
In both cases, you should use classname= as all parameters of these classes are optional. The difference is that the first parameter of Classifier is classname and for WekaEstimator it is the JavaBridge object. That is why it works in the first case, but fails with an Exception in the second case.
Your code should look like this:
import weka.core.jvm as jvm
from weka.classifiers import Classifier
jvm.start()
jrip = Classifier(classname="weka.classifiers.rules.JRip")
jvm.stop()
And:
import sklweka.jvm as jvm
from sklweka.classifiers import WekaEstimator
jvm.start()
jrip = WekaEstimator(classname="weka.classifiers.rules.JRip")
jvm.stop()
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm very new to the coding space and was wondering if someone could help me start a .jar file. BTW This is using C#. My issue is this wont run the file. I got it to work with .txt files though, so I'm just a bit confused.
private void button1_Click(object sender, EventArgs e)
{
Process.Start("java" , "server.jar");
}
In short, for the answer, add -jar right before the JAR file name.
The accepted answer is not 100% correct for several reasons: it does not recognize whitespace-delimited and whitespace-containing arguments, and may mess up with quote characters that must be passed (therefore properly escaped) to the delegated Java app. In short, do not use Arguments if the string is not known to be a constant (having spaces will require manual escaping anyway), but merely prefer ArgumentList that handles each argument properly.
Here is an example Java application to deal with command line arguments:
public final class SayHello {
private SayHello() {}
public static void main(final String... names) {
for ( final String name : names ) {
System.out.printf("hello %s!\n", name);
}
}
}
The manifest for the JAR file:
Manifest-Version: 1.0
Main-Class: SayHello
Making a JAR file out of it is simple:
javac SayHello.java
jar cfm SayHello.jar MANIFEST.MF SayHello.class
Example of use:
java -jar SayHello.jar 'John Doe' Anonymous
that gives:
hello John Doe!
hello Anonymous!
Now, an example C# program that passes the -jar argument to the java process so that it recognizes the given file as a JAR file and demonstrates what can go wrong with Arguments if passed as a string.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
using System.Diagnostics;
public static class SayHello {
public static void Main() {
// interprets 3 names: John, Doe, Anonymous (wrong)
RunJavaJarBadly1("SayHello.jar", "John Doe Anonymous");
// interprets 1 name: John Doe Anonymous (wrong)
RunJavaJarBadly2("SayHello.jar", "John Doe Anonymous");
// interprets 2 names: John Doe, Anonymous (correct, but bad: requires the first name to be quoted at the call-site)
RunJavaJarBadly1("SayHello.jar", "\"John Doe\" Anonymous");
// interprets 1 name: "John Doe" Anonymous (wrong: interprets everything as a single name)
RunJavaJarBadly2("SayHello.jar", "\"John Doe\" Anonymous");
// interprets 2 names, no ambiguous call, each name is recognized properly, does not require quoting at the call site
RunJavaJar("SayHello.jar", "John Doe", "Anonymous");
}
private static void RunJavaJarBadly1(string jarPath, string argumentsFortheJarFile) {
var process = new Process();
process.StartInfo.FileName = "java";
process.StartInfo.Arguments = #"-jar "+ jarPath +" " + argumentsFortheJarFile;
process.Start();
process.WaitForExit();
}
private static void RunJavaJarBadly2(string jarPath, string jarArgs) {
var process = new Process();
process.StartInfo = new ProcessStartInfo("java") {
ArgumentList = { "-jar", jarPath, jarArgs }
};
process.Start();
process.WaitForExit();
}
private static void RunJavaJar(string jarPath, params string[] jarArgs) {
var process = new Process();
process.StartInfo = new ProcessStartInfo("java") {
ArgumentList = { "-jar", jarPath }
};
foreach ( var jarArg in jarArgs ) {
process.StartInfo.ArgumentList.Add(jarArg);
}
process.Start();
process.WaitForExit();
}
}
The code above produces (no legend in the output, but added for explanation):
hello John! \_ #1/1: incorrect, the space is ignored
hello Doe! /
hello Anonymous! -- #1/2: correct, no spaces in-between
hello John Doe Anonymous! -- #2/1|2: incorrect
hello John Doe! -- #3/1: correct, but requires the call site to escape the argument
hello Anonymous! -- #3/2: correct, no need to escape, thanks to no spaces
hello "John Doe" Anonymous! -- #4/1|2: incorrect, similar to #2/1|2
hello John Doe! -- #5/1: correct, let the framework do its job
hello Anonymous! -- #5/2: correct, let the framework do its job
In order to get it to work, the file name needs to be "java" and contain the file location in the arguments.
System.Diagnostics.Process clientProcess = new Process();
clientProcess.StartInfo.FileName = "java";
clientProcess.StartInfo.Arguments = #"-jar "+ jarPath +" " + argumentsFortheJarFile;
clientProcess.Start();
clientProcess.WaitForExit();
int code = clientProcess.ExitCode;
Taken from similar question here
Optional way using ArgumentList:
System.Diagnostics.Process clientProcess = new Process();
var info = new System.Diagnostics.ProcessStartInfo("java.exe")
{
ArgumentList = {
"-jar",
jarPath,
jarArgs
}
};
info.FileName = "java";
clientProcess.StartInfo = info;
clientProcess.Start();
clientProcess.WaitForExit();
int code = clientProcess.ExitCode;
Here are some options for you to check out.
Also similar question with a working result: here
Paraphrasing from links:
In order to get it to work, the file name needs to be "java" and contain the file location in the arguments.
System.Diagnostics.Process clientProcess = new Process();
clientProcess.StartInfo.FileName = "java";
clientProcess.StartInfo.Arguments = #"-jar "+ jarPath +" " + argumentsFortheJarFile;
clientProcess.Start();
clientProcess.WaitForExit();
int code = clientProcess.ExitCode;
I have a tomcat servlet which calls a jar function with parameters. The first parameter sometimes contains space. So I tried to use a String array, but it doesn't work at all.
What am I doing wrong?
requestParm = "java -classpath c:\\j\\test.jar test.connect " + fileName + " new";
requestParmarray =new String[]{"java -classpath c:\\j\\test.jar test.connect ",fileName , " new"};
requestParmarrayNew =new String[]{"java -classpath c:\\j\\test.jar test.connect "+fileName+" new"};
// This line works.but can not handle space well
Process ls_proc = Runtime.getRuntime().exec(requestPar);
// Does not call the function at all
Process ls_proc = Runtime.getRuntime().exec(requestParmarray );
// Does not call the function at all
Process ls_proc = Runtime.getRuntime().exec(requestParmarrayNew );
// Does not call the function at all
Process ls_proc = new ProcessBuilder("java -classpath c:\\j\\test.jar test.connect ",fileName, "new" ).start();
You're creating the array incorrectly: Each individual argument must be in its own entry:
String[] requestParmArray = new String[] {
"java",
"-classpath",
"c:\\j\\test.jar",
"test.connect",
fileName,
"new"
};
Process ls_proc = Runtime.getRuntime().exec(requestParmArray);
Also note that I removed the space you had after test.connect; the spaces you put on the command line are just to separate arguments, but in the above, they're separated by being separate entries in the array.
You should make the array in exec() have each parameter as a separate array entry like:
String[] requestPar = new String[]{"java", "-classpath", "c:\\j\\test.jar", "test.connect ", fileName, "new"};
And use it:
Process ls_proc = Runtime.getRuntime().exec(requestPar);
Hello my problem is as follows:
i have a property fiel with a startconfig for external program to run from java:
# Standardauswahl falls keine PlayerType übergeben wurden
Default = 1
# Liste der gültigen PlayerTypes
PlayerTypes = Human,MCTS,TMM,Random,Value
StartConfig = \"C:\\Program Files\\Java\\jdk1.7.0_13\\bin\\javaw.exe\" -Dlog4j.configuration=file:///C:/Users/djdeejay/git/myGit/com.djdeejay.cowTrade.client.standaloneplayer.application/bin/log4j.xml -Dfile.encoding=Cp1252 -classpath [..... some parameter deleted.....] 0.0-RC1.jar;C:\\Users\\djdeejay\\git\\myGit\\de.thWildau.cowTrade.server\\lib\\slf4j-api-1.5.2.jar;C:\\Users\\djdeejay\\git\\myGit\\de.thWildau.cowTrade.server\\lib\\slf4j-log4j12-1.5.2.jar;C:\\Users\\djdeejay\\git\\myGit\\de.thWildau.cowTrade.server\\lib\\log4j-1.2.16.jar com.djdeejay.cowTrade.client.standaloneplayer.application.RandomPlayerApplication %1 %2 %3
when i load the properties as follows
cmd = this.serverSettings.getPlayerTypeSetting("StartConfig");
#Override
public String getPlayerTypeSetting(String key) {
return this.startPlayerTypeSettingsProp.getProperty(key);
}
java cutting startconfig after the first space:
Cannot run program """C:\Program" when its in doublequotes or Cannot run program ""C:\Program":
i have tried several variants with "", with escaping and so on nothing gives my needed result
how do i config getproperty to read until EOL?
cheers
As discussed in the comments, the getProperty call is alright. But the usage as a single string in Runtime.getRuntime().exec(cmd) uses the default whitespace Tokenizer to split the string into command and argument.
To do this yourself, first split the string manually and then pass it to Runtime#exec:
String startCmdLine = this.serverSettings.getPlayerTypeSetting("StartConfig");
int cmdEndPos = startCmdLine.indexOf("javaw.exe") + "javaw.exe".length();
String cmd = startCmdLine.substring(0, cmdEndPos);
String args = startCmdLine.substring(cmdEndPos);
Runtime.getRuntime().exec(new String[]{ cmd, args });
Though I really advise you to take advantage of the JAVA_HOME environment variable if you just want to start a known java binary. That way you can reduce that to a set of parameters in the property file.
Try replacing your spaces with: "\u0020"
Use this:
StringEscapeUtils.escapeXml(String input);
See doc here