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

Python
256
0
0
2024-02-24
文章目录
  • jpype简介
  • 安装
  • 使用
  • 小试牛刀
  • 使用命令行方式打jar包
  • 调用jar包方法
  • 问题1:shutdownJVM停止后restart失败的情况
  • 问题2:只能调用静态方法
  • 问题3:调用其他包方法
  • 调用jar包main方法
  • java命令行方式运行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.
>>>

  • 安装 jpype
pip install jpype1

第二种:下载whl包安装 下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/

使用

小试牛刀
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包方法

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失败的情况

解决:可以遍历需要调用的类、方法、入参,做个结构体设计,就可以调用多个方法的情况

# -*- 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", ["第一个参数"]]
                     ]
                     )

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

解决:用静态方法调用类方法

问题3:调用其他包方法

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

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