Python使用jpype的踩坑记录

 更新时间:2023年06月20日 09:57:55   作者:一夜奈何梁山  
Pype是一个能够让 python 代码方便地调用 Java 代码的工具,这篇文章主要来和大家分享一下Python使用jpype会踩的一些坑,希望对大家有所帮助

一:需求

近期接到一个需求, 对方部门给了java的jar包和demo。 要求我们与他们进行HTTP通信需要使用他们的Java写的加解密算法进行加密和签名。 我们的服务全部都是PY写的, 因此如果使用PY对对方提供的jar包进行重写, 风险大, 而且开发周期长。 为了快速的解决这样的问题, 我们采用另外的解决方案----- 使用jpype用py直接调用java的jar包。

二:jpype介绍

用途:python调用java包的工具

安装:pip install JPype1

官方文档:https://jpype.readthedocs.io/en/latest/userguide.html

依赖环境:服务器上必须具备Java环境, 如果是容器化部署, 需要先安装Java。

三:jpype的使用

封装jarloader.py 来启动jvm和加载java的类。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time   : 2023/4/4 11:36
# @Author : shanwen.ren@xiaoying.com
# @Notice : java包加载工具
import jpype
from threading import RLock


class JarLoader:
    __rlock = RLock()
    __started = False

    @classmethod
    def start_jvm(cls, classpath, *args):
        if cls.__started:
            return
        with cls.__rlock:
            if not cls.__started:
            	# 加载JVM, 在系统中自动查找
                jvmPath = jpype.getDefaultJVMPath()
                base_args = [jvmPath, "-ea", "-Dfile.encoding=utf-8"]
                base_args += list(args) if args else []
                # 启动JVM
                jpype.startJVM(*base_args, convertStrings=False, classpath=classpath)
                cls.__started = True

    @staticmethod
    def load_class(client_path):
    	# 加载jar包中的类, 返回类, 注意返回的不是对象。 
        Klass = jpype.JClass(client_path)
        return Klass

    @classmethod
    def close(cls):
        jpype.shutdownJVM()  
        cls.__started = False

使用注意事项

class_paths 是所有的jar包列表

例如:

dir_path = os.path.dirname(__file__)
client_sdk_path = os.path.join(dir_path, "java_jars/pd-client-sdk-1.2.jar")
bcprov_path = os.path.join(dir_path, "java_jars/bcprov-jdk15on-1.67.jar")
bcpkix_path = os.path.join(dir_path, "java_jars/bcpkix-jdk15on-1.67.jar")
gson_path = os.path.join(dir_path, "java_jars/gson-2.10.1.jar")
jsch_path = os.path.join(dir_path, "jsch-0.1.55.jar")
class_paths = [client_sdk_path, bcprov_path, bcpkix_path, gson_path, jsch_path]

client_path 是jar包中的实现类路径

例如:client_path = “cn.aaa.sdk.service.impl.XXXX类”

四:类型转换问题

由官方文档可只, 某些类型是可以自动转换的, 而有些是不能转换的。

例如:java类需要传递一个Long类型, 但是Py3中没有Long类型了, 如果直接调用, 抛出类型不一致的问题。

解决方案: python的Int类型先转换成Jlon类型, 然后直接塞到Java的类中。

例如: jpype.JLong(file_size)

五:容器部署问题

容器化部署的时候, 需要依赖Java环境。

解决方案: Dockerfile文件中增加一下指令。

先下载jdk包: 我用的是:jdk-8u181-linux-x64.tar.gz

FROM python:3.8.8 AS builder
# 安装JVM,配置JAVA环境变量
ADD jdk-8u181-linux-x64.tar.gz  /usr/local/jdk
ENV JAVA_HOME=/usr/local/jdk/jdk1.8.0_181 PATH=$JAVA_HOME/bin:$PATH CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.ja

六:JDK版本问题

问题描述:在测试环境是否jpype没有任何的异常, 但是在生产环境部署后, 发现jpype调用java的时候, 路径中的密钥读取不进去。

案例:错误提示: Caused by: java.lang.RuntimeException: java.security.InvalidKeyException: Illegal key size or default parameters at com.

分析原因:

低版本的JDK, 由于美国的出口限制,Sun通过权限文件(local_policy.jar、US_export_policy.jar)做了相应限制。密钥长度最大128。 因此如果密钥超过128位, 就会抛出这个异常。

解决方案:

方案一:升级服务器的JDK版本,我从1.8.0_72,升级到1.8.0_181, 解决了该问题。

方案二:下载Oracle官方网站上的无政策限制权限文件, 替换掉自己版本中的这两个文件(local_policy.jar、US_export_policy.jar)

无限制文件链接:https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

下载后将%JAVA_HOME%\jre\lib\security中的local_policy.jar 和US_export_policy.jar替换为下载包中的的local_policy.jar 和US_export_policy.jar。

到此这篇关于Python使用jpype的踩坑记录的文章就介绍到这了,更多相关Python jpype内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 最新python正则表达式(re模块)详解

    最新python正则表达式(re模块)详解

    在Python中需要通过正则表达式对字符串进⾏匹配的时候,可以使⽤⼀个python自带的模块,名字为re,这篇文章主要介绍了python正则表达式(re模块)详解,需要的朋友可以参考下
    2023-01-01
  • 基于Python实现Excel转Markdown表格

    基于Python实现Excel转Markdown表格

    Markdown(也简称md)作为一种轻量级标记语言,因其易写易读,效果美观大方,不仅被众多网站使用,也是程序员们做笔记、写文档的首选。本文将利用Python实现Excel转Markdown表格,感兴趣的可以了解一下
    2022-04-04
  • Python编程实现从字典中提取子集的方法分析

    Python编程实现从字典中提取子集的方法分析

    这篇文章主要介绍了Python编程实现从字典中提取子集的方法,结合实例形式对比分析了Python采用字典推导式与序列转换实现字典提取子集的相关操作技巧与优缺点,需要的朋友可以参考下
    2018-02-02
  • 解决Python字典查找报Keyerror的问题

    解决Python字典查找报Keyerror的问题

    这篇文章主要介绍了解决Python字典查找报Keyerror的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05
  • Python简单I/O操作示例

    Python简单I/O操作示例

    这篇文章主要介绍了Python简单I/O操作,结合实例形式分析了Python针对文件的I/O读写及cPickle模块相关使用操作技巧,需要的朋友可以参考下
    2019-03-03
  • python轻松办公将100个Excel中符合条件的数据汇总到1个Excel里

    python轻松办公将100个Excel中符合条件的数据汇总到1个Excel里

    这篇文章主要为大家介绍了python轻松办公将100个Excel中符合条件的数据汇总到1个Excel里示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Python使用tkinter模块实现GUI界面的学生信息管理系统流程分步详解

    Python使用tkinter模块实现GUI界面的学生信息管理系统流程分步详解

    这篇文章主要为大家详细介绍了python实现简易学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2023-01-01
  • Python线性方程组求解运算示例

    Python线性方程组求解运算示例

    这篇文章主要介绍了Python线性方程组求解运算,涉及Python使用scipy.linalg.solve进行方程组求解运算的相关操作技巧,需要的朋友可以参考下
    2018-01-01
  • python如何通过注册表动态管理组件

    python如何通过注册表动态管理组件

    使用注册表的主要优势是可以在运行时动态创建对象,从而实现高度可配置和可扩展的设计,这篇文章主要介绍了python如何通过注册表动态管理组件,需要的朋友可以参考下
    2024-05-05
  • 详解Golang 与python中的字符串反转

    详解Golang 与python中的字符串反转

    这篇文章主要介绍了详解Golang 与python中的字符串反转的相关资料,这里提供了实现的实例以便大家学习理解,需要的朋友可以参考下
    2017-07-07

最新评论