Jython allows you to run Python scripts on the JVM. Is there anyone who uses it? You might think, but it's me. I'm here.
Jython
Originator http://www.jython.org/ wikipedia https://ja.wikipedia.org/wiki/Jython
I will write how to use (Java code) and addictive points.
When I googled it, I got the impression that there are many ways to install it and use it from the command line, but this time I will run it from Java code.
First maven pom.xml
pom.xml
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.0</version>
</dependency>
import java.util.Properties;
import org.python.util.PythonInterpreter;
//・ ・ ・
public static void main(String[] args) {
Properties props = new Properties();
props.put("python.console.encoding", "UTF-8");
PythonInterpreter.initialize(System.getProperties(), props, new String[0]);
try (PythonInterpreter interp = new PythonInterpreter()) {
interp.exec("a = 1 + 2");
interp.exec("print(a)");
}
}
Result (console)
3
I wasn't sure exactly what python.console.encoding
was, but I got an error if it wasn't there, so when I googled it, I wrote it like this.
import org.python.core.PyInteger;
import org.python.core.PyObject;
//・ ・ ・
public static void main(String[] args) {
Properties props = new Properties();
props.put("python.console.encoding", "UTF-8");
PythonInterpreter.initialize(System.getProperties(), props, new String[0]);
try (PythonInterpreter interp = new PythonInterpreter()) {
PyInteger x = new PyInteger(10);
interp.set("x", x);//Substitute 10 for x
interp.exec("a = x + 2");
PyObject a = interp.get("a");//Get the result of a
System.out.println(a);
System.out.println(a.getClass());
}
}
result
12
class org.python.core.PyInteger
There are various implementation classes of PyObject, and you can set and get them to exchange Java code and Python code.
PyInteger if you want to pass int, PyString if you want to pass str ... I think Japanese people are addicted to it here. See next.
PyString s = new PyString("AIUEO");
When I try to generate a PyString with the string " AIUEO "
, it looks like this.
Exception in thread "main" java.lang.IllegalArgumentException: Cannot create PyString with non-byte value
at org.python.core.PyString.<init>(PyString.java:64)
at org.python.core.PyString.<init>(PyString.java:70)
at ....main(・ ・ ・ ・)
Gununu. The first thing to understand is that Jython has Python 2 support. Python3 code does not work. (I was studying only Python3 so I was disappointed)
Python2 had to be unicode. So
public static void main(String[] args) {
Properties props = new Properties();
props.put("python.console.encoding", "UTF-8");
PythonInterpreter.initialize(System.getProperties(), props, new String[0]);
try (PythonInterpreter interp = new PythonInterpreter()) {
PyUnicode s = new PyUnicode("AIUEO");
interp.set("s", s);
interp.exec("a = s * 10");
PyObject a = interp.get("a");
System.out.println(a);
System.out.println(a.getClass());
}
}
Aiue Aiue Aiue Aiue Aiue Aiue Aiue Aiue Aiue Aiue Aiue
class org.python.core.PyUnicode
I was able to do it.
Encode it on a Python script and handle it with str.
public static void main(String[] args) {
Properties props = new Properties();
props.put("python.console.encoding", "UTF-8");
PythonInterpreter.initialize(System.getProperties(), props, new String[0]);
try (PythonInterpreter interp = new PythonInterpreter()) {
PyUnicode s = new PyUnicode("AIUEO");
interp.set("s", s);
interp.exec("s = s.encode('utf-8')");
interp.exec("a = s * 10");
PyObject a = interp.get("a");
System.out.println(a);
System.out.println(a.getClass());
}
}
ãããããããããããããããããããããããããããããããããããããããããããããããããã
class org.python.core.PyString
Somehow I was expecting it. Rewrite
public static void main(String[] args) {
Properties props = new Properties();
props.put("python.console.encoding", "UTF-8");
PythonInterpreter.initialize(System.getProperties(), props, new String[0]);
try (PythonInterpreter interp = new PythonInterpreter()) {
PyUnicode s = new PyUnicode("AIUEO");
interp.set("s", s);
interp.exec("s = s.encode('utf-8')");
interp.exec("a = s * 10");
interp.exec("a = a.decode('utf-8')");
PyObject a = interp.get("a");
System.out.println(a);
System.out.println(a.getClass());
}
}
Aiue Aiue Aiue Aiue Aiue Aiue Aiue Aiue Aiue Aiue Aiue
class org.python.core.PyUnicode
It was OK if I decoded it to unicode before taking the variable.
public static void main(String[] args) {
Properties props = new Properties();
props.put("python.console.encoding", "UTF-8");
PythonInterpreter.initialize(System.getProperties(), props, new String[0]);
try (PythonInterpreter interp = new PythonInterpreter()) {
PyUnicode s = new PyUnicode("a ah");
interp.set("s", s);
interp.exec("s = s.encode('utf-8')");
interp.exec("a = s.upper()");
interp.exec("a = a.decode('utf-8')");
PyObject a = interp.get("a");
System.out.println(a);
System.out.println(a.getClass());
}
}
Where to expect the result ʻA a`
Exception in thread "main" Traceback (most recent call last):
File "<string>", line 1, in <module>
File "・ ・ ・\repository\org\python\jython-standalone\2.7.0\jython-standalone-2.7.0.jar\Lib\encodings\utf_8.py", line 16, in decode
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 3: unexpected code byte
When I upper it on Python, it seems to be an error because it is new PyString ()
and contains multibyte characters. maybe.
It seems that there is no workaround here other than writing the code carefully. You should use unicode instead of str.
(Please point out if there is a method)
But if it's used in an external Python library, it can't be helped. Wonder? .. .. ..
Create the following py file in some directory
sample.py
# coding:utf-8
def add_numbers(a, b):
return a + b
Load and execute this
public static void main(String[] args) {
Properties props = new Properties();
props.put("python.path", "[Sample above.Directory with py]");
props.put("python.console.encoding", "UTF-8");
PythonInterpreter.initialize(System.getProperties(), props, new String[0]);
try (PythonInterpreter interp = new PythonInterpreter()) {
interp.exec("import sample"); //sample.import py
interp.exec("a = sample.add_numbers(2, 3)");
interp.exec("print(a)");
}
}
5
Set the directory to python.path
.
If there are multiple, it seems that it can be handled by connecting them with a delimiter. (Windows ;
)
http://www.jython.org/archive/22/userfaq.html#my-modules-can-not-be-found-when-imported-from-an-embedded-application
sys.path.append
from the python code.
(I haven't tried it in the jar yet.)You can also run the py file in the jar.
How to specify
Specify [Path.jar with Jar] \ [folder name in jar with py file]
.
If there is a py file in a folder called python in the jar, write it like this.
props.put("python.path", "C:/・ ・ ・ ・.jar/python");
If you know that it exists in the python folder, you can write it like this.
public static void main(String[] args) {
Properties props = new Properties();
props.put("python.path", getPythonPath());
props.put("python.console.encoding", "UTF-8");
PythonInterpreter.initialize(System.getProperties(), props, new String[0]);
try (PythonInterpreter interp = new PythonInterpreter()) {
interp.exec("import sample");
interp.exec("a = sample.add_numbers(2, 3)");
interp.exec("print(a)");
}
}
private static String getPythonPath() {
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL root = classLoader.getResource("python");
if ("file".equals(root.getProtocol())) {
Path path = Paths.get(root.toURI());
return path.toString();
} else if ("jar".equals(root.getProtocol())) {
URI jarFileUri = new URI(root.getPath().replaceFirst("!/.*$", ""));
Path path = Paths.get(jarFileUri);
return path.resolve("python").toString();
}
} catch (URISyntaxException e) {
throw new IllegalStateException(e);
}
throw new IllegalStateException("python directory not found");
}
This allows you to run both flat py files and jar-packed py files. Now you don't have to rewrite the code for development and deployment.
Finally
First of all, I have to study the 2nd system. .. ..
Recommended Posts