[1250]python调用java代码的工具jpype

文章目录

    • jpype简介
    • 安装
    • 使用
      • 小试牛刀
      • 使用命令行方式打jar包
      • 调用jar包方法
        • 问题1:shutdownJVM停止后restart失败的情况
        • 问题2:只能调用静态方法
        • 问题3:调用其他包方法
      • 调用jar包main方法
        • java命令行方式运行jar包
    • python使用jpype导入多个Jar的异常问题

jpype简介

JPype是一个能够让 python 代码方便地调用 Java 代码的工具,从而克服了 python 在某些领域(如服务器端编程)中的不足。

Jython 是给 Java程序员 运行 Python 程序用的。JPype是给python程序员玩的

github:https://github.com/jpype-project/jpype

安装

注意点:python和java的位数一定要一致

C:\Users\admin>java -version
java version "1.8.0_311"
Java(TM) SE Runtime Environment (build 1.8.0_311-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.311-b11, mixed mode)

C:\Users\admin>python
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

[1250]python调用java代码的工具jpype_第1张图片

  • 安装 jpype
pip install jpype1

第二种:下载whl包安装
下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/
[1250]python调用java代码的工具jpype_第2张图片

使用

小试牛刀

import os
import jpype


# 使用自定义jvm
# jvmPath = r'D:\soft\java\jdk\jre\bin\server\jvm.dll'
# 使用java环境默认jvm
jvmPath = jpype.getDefaultJVMPath()
print('jvmPath:',jvmPath)

jpype.startJVM(jvmPath)
jpype.java.lang.System.out.println("hello world!")
jpype.shutdownJVM()

输出结果:

hello world!

注意点:JAVA_HOME一定要配置对,要不然找不到

jpype.getDefaultJVMPath() #这里说明了其实我们不用装JDK只要安装和python位数一致的JRE就行了
这个也是可以配置的:默认的是使用的JDK中自带的jre,我们可以只安装jre的情况下指定这个路径

使用命令行方式打jar包

在Java中,可以使用以下命令将代码打包为jar包:

使用命令行方式:
使用javac命令编译源代码文件为class文件:javac MyClass.java
使用jar命令创建jar包:jar cf myJar.jar MyClass.class
这将编译MyClass.java文件并将生成的class文件打包到名为myJar.jar的jar包中。

调用jar包方法

[1250]python调用java代码的工具jpype_第3张图片


import os
import jpype
 
 
def java_class_func(jar_path, class_name, func_name, jvm_path=None, *args):
    """
    调用jar包中class下的方法
    :return:
    """
    # jar包路径的配置
    # jarpath = os.path.join(os.path.abspath("."), "D:\\hf-0.1.jar")
    jarpath = os.path.join(os.path.abspath(".."), jar_path)
    # 这里指定了jvm
    if jvm_path:
        jvmpath = jvm_path
    else:
        jvmpath = jpype.getDefaultJVMPath()
    jpype.startJVM(jvmpath, "-ea", "-Djava.class.path=%s" % jarpath)
 
    # 这里是指定哪个class,执行哪个方法,入参和结果展示
    # java_class = jpype.JClass("com.dubbo.testjsf.R2mUtils")
    # java_class.getCustKeys()
    
    java_class = jpype.JClass(class_name)
    ru_param = ','.join(list(map(lambda x: json.dumps(x), args)))
 
    ########################################################################
    # 判断是否有中文在里面,有就转成unicode,后来发现是pycharm的编码格式问题,这里就注释了
    # def _iszh(p):
    #     for c in p:
    #         if '\u4e00' <= c <= '\u9fa5':
    #             return True
    #     return False
    #
    # args_list = list(map(lambda x: json.dumps(x) if _iszh(x) else x, args))
    ########################################################################
 
    res = eval("java_class.%s(%s)" % (func_name, ru_param))
    print(res)  # 打印有返回值方法的结果
    jpype.shutdownJVM()
 
 
if __name__ == '__main__':
    java_class_func(r"D:\mycode\javacode\jsf_hf_demo\hf\target\hf-0.2.jar",
                    "com.dubbo.testjpype.Jpype",
                    "func1",
                    "C:\\Java\\jre\\bin\\client\\jvm.dll")
    java_class_func(r"D:\mycode\javacode\jsf_hf_demo\hf\target\hf-0.2.jar",
                    "com.dubbo.testjpype.Jpype",
                    "func4",
                    "C:\\Java\\jre\\bin\\client\\jvm.dll",
                    "第一个参数",
                    "第二个参数")
 
    java_class_func(r"D:\mycode\javacode\jsf_hf_demo\hf\target\hf-0.2.jar",
                    "com.dubbo.testjpype.Jpype",
                    "func2",
                    None,
                    "第一个参数")
 
    java_class_func(r"D:\mycode\javacode\jsf_hf_demo\hf\target\hf-0.2.jar",
                    "com.dubbo.testjpype.Jpype",
                    "func3",
                    None,
                    "1",
                    3)
问题1:shutdownJVM停止后restart失败的情况

解决:可以遍历需要调用的类、方法、入参,做个结构体设计,就可以调用多个方法的情况
[1250]python调用java代码的工具jpype_第4张图片

# -*- coding:utf-8 -*-
import json
import os
 
import jpype
 
def java_class_func1(jar_path, actions, jvm_path=None):
    """
    调用jar包中class下的方法
    :return:
    """
    jarpath = os.path.join(os.path.abspath(".."), jar_path)
    # 这里指定了jvm
    if jvm_path:
        jvmpath = jvm_path
    else:
        jvmpath = jpype.getDefaultJVMPath()
    jpype.startJVM(jvmpath, "-ea", "-Djava.class.path=%s" % jarpath)
 
    for class_name, func_name, in_params in actions:
        java_class = jpype.JClass(class_name)
        ru_param = ','.join(list(map(lambda x: json.dumps(x), in_params)))
        res = eval("java_class.%s(%s)" % (func_name, ru_param))
        print(res)  # 打印有返回值方法的结果
    jpype.shutdownJVM()
 
 
if __name__ == '__main__':
    java_class_func1(r"D:\mycode\javacode\jsf_hf_demo\hf\target\hf-0.2.jar",
                     [
                         ["com.dubbo.testjpype.Jpype", "func1", []],
                         ["com.dubbo.testjpype.Jpype", "func2", ["第一个参数"]]
                     ]
                     )

[1250]python调用java代码的工具jpype_第5张图片

问题2:只能调用静态方法

解决:用静态方法调用类方法
[1250]python调用java代码的工具jpype_第6张图片
[1250]python调用java代码的工具jpype_第7张图片

问题3:调用其他包方法

[1250]python调用java代码的工具jpype_第8张图片


if __name__ == '__main__':
    java_class_func1(r"D:\mycode\javacode\jsf_hf_demo\hf\target\hf-0.2.jar",
                     [
                         ["com.dubbo.testjsf.JpypeThree", "func1", []],
                         ["com.dubbo.testjpype.JpypeOther", "func1", []],
                         ["com.dubbo.testjpype.Jpype", "func1", []],
                         ["com.dubbo.testjpype.Jpype", "func2", ["第一个参数"]],
                         ["com.dubbo.testjpype.Jpype", "func3", ["1", 3]],
                         ["com.dubbo.testjpype.Jpype", "func4", ["第一个参数", "第二个参数"]],
                         ["com.dubbo.testjpype.Jpype", "func5", []],
                         ["com.dubbo.testjpype.Jpype", "func0", []]
                     ]
                     )

调用jar包main方法


# -*- coding:utf-8 -*-
import json
import os
 
import jpype
 
def java_class_main(jar_path, class_name, main_args, jvm_path=None):
    """
    调用jar包中class下的main方法
    :return:
    """
    jarpath = os.path.join(os.path.abspath(".."), jar_path)
    if jvm_path:
        jvmpath = jvm_path
    else:
        jvmpath = jpype.getDefaultJVMPath()
    jpype.startJVM(jvmpath, "-ea", "-Djava.class.path=%s" % jarpath)
    # 使用JClass调用main方法
    # jpype.JClass(class_name).main(main_args)
    # 使用JPackage调用main方法
    # jpype.JPackage("com").dubbo.testlala.Jpype.main(main_agrs)
    v1, v2 = class_name.split(".", 1)
    eval('jpype.JPackage("%s").%s.main(%s)' % (v1, v2, main_args))
    jpype.shutdownJVM()
 
if __name__ == '__main__':
        java_class_main(r"D:\mycode\javacode\jsf_hf_demo\hf\target\hf-0.2.jar",
                    "com.dubbo.testjpype.Jpype",
                    '["第一个参数","第二个参数","第三个参数"]')
java命令行方式运行jar包
# 指定jar中调用那个class的main函数(java -cp jar的路径 class路径)
java -cp .\hf\target\hf-0.1.jar com.dubbo.testjsf.Get22

#jar中调用MANIFEST.MF配置的入口class的main函数
java -jar .\hf\target\hf-0.1.jar

#main方法有入参的情况(java -cp jar包路径 class路径  main的入参多个就空格分开)
java -cp .\hf\target\hf-0.1.jar com.dubbo.testjsf.Get22 "15910843034" "143121321"
java -cp .\hf\target\hf-0.1.jar com.dubbo.testjsf.Get22 asktest dsf

python使用jpype导入多个Jar的异常问题

在使用Jpype导入多个Jar包时,采用以下代码在linux系统执行时会抛出异常。

jar_path1 = './lib/A.jar'
jar_path2 = './lib/B.jar'
jar_path = "-Djava.class.path=%s;%s"%(jar_path1,jar_path2)

TypeError: Class com.XXX.XXX.XXX is not found

这个异常源于linux系统和windows系统间隔符的问题。
采用以下加载方法顺利解决问题

jpype.startJVM('-ea', classpath=['path1', 'path2'])
print(jpype.java.lang.System.getProperty('java.class.path'))

参考:https://blog.csdn.net/chenchen_nini/article/details/123878699
https://www.python100.com/html/4ZZ134CWW17K.html
https://blog.csdn.net/weixin_38358881/article/details/123051855

你可能感兴趣的:(Python前行者,python,java)