在java中使用jython

jython的版本和python都是一一对应的,jython现在更新到了2.7,对应的也就是python2.7.

jython有安装板和独立版,安装板的就像python,需要安装到主机使用,独立版的就是一个jar包,可以在cmd中运行,也可以直接放在java项目中使用,

下载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);
    }
}

 

测试一下,

 

jython启动了,但没有输出,报错不识别这个命令,

当然不识别了,我没有给helloworld加引号,字符串当然要加引号才能识别了

这样就可以了,

新建一个脚本  

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);
    }
}

 

 

 

多参数试一下

# 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);
    }
}

测试一下

 

这里要注意的是,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()

 

测试下

 

成功写出

jython的运用方法有很多种,但是ascli码的限制让传值有很大的限制,py.newStringUTF8()就是个骗人的玩意,并不能发送中文

说起这个传值,就不得不提一下python2时代 的各种坑爹了

之前在写出方法中,一直采用的直接转成json当做参数传给方法,json也是字符串嘛,奈何io流毕竟小水管,没办法一次发送字节超过20万的字符串,后来就想到传byte数组,我转成byte数组总没问题吧,这样一来,中文问题都解决了,啊,我真是太机智了

too young too simple

直接报错,不识别非ascll码的值,

看的我一脸懵逼啊,字节数组不应该啊,都是数字啊,

隐约觉得那里不对劲

在我点开python2.5的源码的时候,我差点就要失意体前屈了

 

bytes=str

 

好嘛,直接将字符串赋给字节数组,真是天人合一,天下无敌啊

每次想起这件事,我都想深切对python的设计师说一句

标题

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

离离原上草77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值