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.
>>>
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的情况下指定这个路径
在Java中,可以使用以下命令将代码打包为jar包:
使用命令行方式:
使用javac命令编译源代码文件为class文件:javac MyClass.java
使用jar命令创建jar包:jar cf myJar.jar MyClass.class
这将编译MyClass.java文件并将生成的class文件打包到名为myJar.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)
解决:可以遍历需要调用的类、方法、入参,做个结构体设计,就可以调用多个方法的情况
# -*- 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", ["第一个参数"]]
]
)
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", []]
]
)
# -*- 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",
'["第一个参数","第二个参数","第三个参数"]')
# 指定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
在使用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