天天看點

在java中使用jython

jython的版本和python都是一一對應的,jython現在更新到了2.7,對應的也就是python2.7.

jython有安裝闆和獨立版,安裝闆的就像python,需要安裝到主機使用,獨立版的就是一個jar包,可以在cmd中運作,也可以直接放在java項目中使用,

在java中使用jython

下載下傳jython Standalone獨立版

添加到java項目中

然後建立解析器

package demo3;

import org.python.core.*;
import org.python.util.PythonInterpreter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Properties;

public class jythonshellInter {
    public String name;
    public PythonInterpreter interpreter;

    public jythonshellInter() {
    }

    public jythonshellInter(String name) {
        this.name = name;
        jythonInit();
    }

    public void jythonInit() {
        //初始化site 配置
        Properties props = new Properties();
        props.put("python.console.encoding", "UTF-8");
        props.put("python.home", "/lib/jython-standalone-2.7.2b2.jar"); //python Lib 或 jython Lib,根據系統中該檔案目錄路徑
        props.put("python.security.respectJavaAccessibility", "false");
        props.put("python.import.site", "false");
        Properties preprops = System.getProperties();
        PythonInterpreter.initialize(preprops, props, new String[0]);
        PySystemState sys = Py.getSystemState();
        sys.path.add(System.getProperty("user.dir") + "");
        //建立PythonInterpreter 對象

        interpreter = new PythonInterpreter();
    }

    /**
     * 執行指令
     *
     * @param cmd
     */
    public boolean execute(String cmd) {
        PyString str = Py.newStringUTF8(cmd);
        boolean falg;
        try {
            interpreter.exec(str);
            falg = true;
        } catch (PyException e) {
            System.out.println(e.type + "\t" + e.value);
            falg = false;
        }
        return falg;
    }

    public boolean execFile(File file) {
        boolean flag;
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            interpreter.execfile(fileInputStream);
            flag = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            flag = true;
        } catch (PyException e) {
            System.out.println(e.type + "\n" + e.value);
            flag = true;
        }
        return flag;
    }

    public void loadFile(String filePath) {
        try {
            interpreter.execfile(filePath);
        } catch (PyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 獲得方法的類型
     *
     * @param interpreter
     * @param funcName
     * @return
     */
    public PyFunction loadPuthonFunc(PythonInterpreter interpreter, String funcName) {
        PyFunction pyFunction = interpreter.get(funcName, PyFunction.class);
        return pyFunction;
    }

    /**
     * 執行無參數方法
     * 傳回obj
     *
     * @param function
     * @return
     */
    public Object execFunc(PyFunction function) {
        PyObject pyObject = null;
        try {
            pyObject = function.__call__();
        } catch (PyException e) {
            e.printStackTrace();
        }
        return pyObject.__tojava__(Object.class);
    }

    /**
     * 執行多參數下的方法
     *
     * @param function
     * @param values
     * @return
     */
    public Object execFuncOfArr(PyFunction function, String... values) {
        PyString[] strings = new PyString[values.length];
        for (int i = 0; i < strings.length; i++) {
            strings[i] = Py.newString(values[i]);
        }
        PyObject pyObject = null;
        try {
            pyObject = function.__call__(strings);
        } catch (PyException e) {
            e.printStackTrace();
        }
        return pyObject.__tojava__(Object.class);
    }

    /**
     * 取出在解析器儲存的資料
     *
     * @param name
     * @return
     */
    public Object getData(String name) {

        PyObject pyObject = interpreter.get(name);
        return pyObject.__tojava__(Object.class);
    }
}
           

測試一下,

在java中使用jython

jython啟動了,但沒有輸出,報錯不識别這個指令,

當然不識别了,我沒有給helloworld加引号,字元串當然要加引号才能識别了

在java中使用jython

這樣就可以了,

建立一個腳本  

test.py

#coding=utf8

def testStrAdd(str):
    return str+"123"
           

jythonTest測試類

package demo3;

import org.python.core.PyFunction;

import java.io.File;

public class jythonTest {
    public static void main(String[] args) {
        jythonshellInter shellInter = new jythonshellInter("");
        String path = System.getProperty("user.dir") + "/resources/test.py";
        shellInter.loadFile(path);
        PyFunction function = shellInter.loadPuthonFunc(shellInter.interpreter, "testStrAdd");
        Object hello = shellInter.execFuncOfArr(function, "hello");
        System.out.println(hello);
    }
}
           
在java中使用jython

多參數試一下

# coding=utf8

def testStrAdd(*str):
    a = ""
    for i in str:
        a = a + i + "*"
    return a
           
package demo3;

import org.python.core.PyFunction;

import java.io.File;

public class jythonTest {
    public static void main(String[] args) {
        jythonshellInter shellInter = new jythonshellInter("");
        String path = System.getProperty("user.dir") + "/resources/test.py";
        shellInter.loadFile(path);
        PyFunction function = shellInter.loadPuthonFunc(shellInter.interpreter, "testStrAdd");
        Object hello = shellInter.execFuncOfArr(function, "hello", "world", "!");
        System.out.println(hello);
    }
}
           

測試一下

在java中使用jython

這裡要注意的是,jython是2版本的python,解析的全部是ASCII編碼 ,對中文的支援很差,(不過其他國家語言也一樣),并且像特殊符号也不能寫入,比如西格瑪,蘭姆達這樣的希臘字元,都是不能輸入的,

jython在執行python腳本的時候,我們可以直接将對象存入解析器中,這樣就可以實作大容量或者不規整無法使用json寫出的資料傳入py腳本,直接操作對象肯定比json二次錄入要高效的多,

傳入py檔案的對象,要使用java的表達式進行操作,

建立一個user類

package demo3;

public class User {
    String name;
    int age;
    double hight;

    public User(String name, int age, double hight) {
        this.name = name;
        this.age = age;
        this.hight = hight;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getHight() {
        return hight;
    }

    public void setHight(double hight) {
        this.hight = hight;
    }
}
           

寫一個user的集合放入jython的解析器中

package demo3;

import org.python.core.PyFunction;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class jythonTest {
    public static void main(String[] args) {
        jythonshellInter shellInter = new jythonshellInter("");
        String path = System.getProperty("user.dir") + "/resources/test.py";
        shellInter.loadFile(path);
        PyFunction function = shellInter.loadPuthonFunc(shellInter.interpreter, "userWriter");


        List<User> users = new ArrayList<>();
        users.add(new User("faker", 20, 182.0));
        users.add(new User("uzi", 21, 183.0));
        users.add(new User("jax", 22, 184.0));
        shellInter.interpreter.set("data", users);
        String filePath = "D:\\";
        String fileName = "text.txt";
        Object hello = shellInter.execFuncOfArr(function, filePath, fileName);
        System.out.println(hello);
    }
}
           

建立一個檔案寫出的方法,解析java對象,并寫出對象屬性到檔案

# coding=utf8
import codecs


def testStrAdd(*str):
    a = ""
    for i in str:
        a = a + i + "*"
    return a


def userWriter(filePath, fileName):
    try:
        file = codecs.open(filePath + "/" + fileName, "w")
        wire = ""
        for user in data:
            wire = user.getName() + "\t" + str(user.getAge()) + "\t" + str(user.getHight()) + "\n"
            file.write(wire)
    finally:
        file.close()
           

測試下

在java中使用jython

成功寫出

jython的運用方法有很多種,但是ascli碼的限制讓傳值有很大的限制,py.newStringUTF8()就是個騙人的玩意,并不能發送中文

說起這個傳值,就不得不提一下python2時代 的各種坑爹了

之前在寫出方法中,一直采用的直接轉成json當做參數傳給方法,json也是字元串嘛,奈何io流畢竟小水管,沒辦法一次發送位元組超過20萬的字元串,後來就想到傳byte數組,我轉成byte數組總沒問題吧,這樣一來,中文問題都解決了,啊,我真是太機智了

too young too simple

直接報錯,不識别非ascll碼的值,

看的我一臉懵逼啊,位元組數組不應該啊,都是數字啊,

隐約覺得那裡不對勁

在我點開python2.5的源碼的時候,我差點就要失意體前屈了

bytes=str

好嘛,直接将字元串賦給位元組數組,真是天人合一,天下無敵啊

每次想起這件事,我都想深切對python的設計師說一句

在java中使用jython

标題