Summary of calling Python methods in Java and stepping on pit records

foreword

Recently, I need to call Python scripts through Java in a project. I searched many blogs on the Internet, and stepped on a lot of pitfalls during the whole operation process. Therefore, this article makes a summary of calling Python in Java and the problems encountered.

calling method

Call through Runtime

Examples are as follows:

public class InvokeByRuntime {
    
    
	/**
	 * @param args
	 * @throws IOException 
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws IOExceptionInterruptedException {
    
    
		String exe = "python";
		String command = "D:\\calculator_simple.py";
		String num1 = "1";
		String num2 = "2";
		String[] cmdArr = new String[] {
    
    exe, command, num1, num2};
		Process process = Runtime.getRuntime().exec(cmdArr);
		InputStream is = process.getInputStream();
		DataInputStream dis = new DataInputStream(is);
		String str = dis.readLine();
		process.waitFor();
		System.out.println(str);
	}
}

caculator_simple.py:

# coding=utf-8
from sys import argv

num1 = argv[1]
num2 = argv[2]
sum = int(num1) + int(num2)
print sum

output:

3

This method has the same effect as directly executing the Python program. Python can read the parameters passed by Java, but the disadvantage is that the result cannot be returned through the return statement in Python, and the return value can only be written to the standard output stream, and then used Java reads the output value of Python

Called by Jython

Introduce dependencies in the maven project, the latest version is used here

<dependency>
  <groupId>org.python</groupId>
  <artifactId>jython-standalone</artifactId>
  <version>2.7.2</version>
</dependency>

no parameter no return value

example:

package com.poas.utils;
import org.python.util.PythonInterpreter;

public class PythonTest {
    
    
    public static void main(String[] args) {
    
    
        PythonInterpreter interpreter = new PythonInterpreter();
        //这里用的是相对路径,注意区分
        interpreter.execfile("core/src/main/java/com/poas/utils/plus.py");
      
      	interpreter.cleanup();
        interpreter.close();
    }
}

plus.py:

a = 1
b = 2
print(a + b)

output

3

There are parameters and return values

example:

package com.poas.utils;

import org.python.core.PyFunction;
import org.python.core.PyInteger;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;

public class PythonTest {
    
    
    public static void main(String[] args) {
    
    
        PythonInterpreter interpreter = new PythonInterpreter();
        //我在这里使用相对路径,注意区分
        interpreter.execfile("core/src/main/java/com/poas/utils/plus.py");

        // 第一个参数为期望获得的函数(变量)的名字,第二个参数为期望返回的对象类型
        PyFunction pyFunction = interpreter.get("add", PyFunction.class);
        int a = 5, b = 10;
        //调用函数,如果函数需要参数,在Java中必须先将参数转化为对应的“Python类型”
        PyObject pyobj = pyFunction.__call__(new PyInteger(a), new PyInteger(b));
        System.out.println("the anwser is: " + pyobj);
      
      	interpreter.cleanup();
        interpreter.close();
    }
}

plus.py:

def add(a,b):
    return a+b

After execution, the result is 15

Trample record

Most of the blogs on the Internet have reached the above part, but I also encountered the following problems in practice

报错: Non-ASCII character in file xxx, but no encoding declared

The reason is that there is Chinese in the python file, which cannot be recognized, even if it is a comment.

in the python filefirst rowAdd the following content, the problem is solved

# -*- coding: utf-8 -*-

报错:Cannot create PyString with non-byte value

The jython version I used at the beginning was 2.7.0, and this error was reported when passing strings in Java: Cannot create PyString with non-byte value; I checked on the Internet and said it was a version problem, so I updated the version to 2.7.2, the problem solve

Error: ImportError: No module named xxx

I referenced a third party library in my python file and as a result I got this error

Java file:

public class PythonTest {
    
    
    public static void main(String[] args) {
    
    
        PythonInterpreter interpreter = new PythonInterpreter();       
        interpreter.execfile("core/src/main/java/com/poas/utils/hello.py");        
        PyFunction pyFunction = interpreter.get("hello", PyFunction.class);        
        PyString str = Py.newString("hello world!");
        PyObject pyobj = pyFunction.__call__(str);
        System.out.println(pyobj);
      
      	interpreter.cleanup();
        interpreter.close();
    }
}

python file:

import requests #此处这个包没有实际作用,只是为了复现报错
def hello(str) :
    print(str)
    return str

Error:

ImportError: No module named requests

First check whether the corresponding third-party library is installed. After success in the python environment, it means that the corresponding module has been installed; after searching on the Internet, it is found that it needs to be configuredpython system path,code show as below:

public class PythonTest {
    
    
    public static void main(String[] args) {
    
    
		// 配置python的系统路径
        System.setProperty("python.home", "/usr/bin/python2.7");

        PythonInterpreter interpreter = new PythonInterpreter()
        interpreter.execfile("core/src/main/java/com/poas/utils/hello.py");        
        PyFunction pyFunction = interpreter.get("hello", PyFunction.class);        
        PyString str = Py.newString("hello world!");
        PyObject pyobj = pyFunction.__call__(str);
        System.out.println(pyobj);
      
      	interpreter.cleanup();
        interpreter.close();
    }
}

After the configuration is complete, the error is still reported

Continue to check the information, in addition to the above configuration, but also theThe path of the referenced third-party libraryAdd to the system environment variable, the code is as follows:

public class PythonTest {
    
    
    public static void main(String[] args) {
    
    
        // 配置python的系统路径
        System.setProperty("python.home", "/usr/bin/python2.7");

        PythonInterpreter interpreter = new PythonInterpreter();
        // 添加第三方库的路径
        PySystemState sys = interpreter.getSystemState();
        sys.path.add("/Users/xxx/Library/Python/2.7/lib/python/site-packages");

        interpreter.execfile("core/src/main/java/com/poas/utils/hello.py");
        PyFunction pyFunction = interpreter.get("hello", PyFunction.class);
        PyString str = Py.newString("hello world!");
        PyObject pyobj = pyFunction.__call__(str);
        System.out.println(pyobj);
        interpreter.cleanup();
        interpreter.close();
    }
}

problem solved

references:

Call Python in Java
[Java] Four ways to call Python using Java

Guess you like

Origin blog.csdn.net/wzc3614/article/details/128666187