背景与需求

  1. 最近学习并安装使用了 HttpRunner 框架去尝试做接口测试,并有后续在公司推广的打算。
  2. HttpRunner 由 Python 开发,调用接口时需要依赖 Python;而大多数公司的扩展工具包使用 Java 编写,测试同学使用 Python 重新实现不显示。
  3. 目前网上的资料均停留在对单个 JAR 包的引用于使用上,对于使用多个有依赖关系的 JAR 包的方法并未提及。

JPype 介绍

1. JPype 是什么:

JPype 是一个能够让 python 代码方便地调用 Java 代码的工具,从而克服了 python 在某些领域(如服务器端编程)中的不足。
JPype 的实际运行环境仍然是 python runtime,只是在运行期间启动了一个嵌入的 jvm。

2. 环境搭建

我的开发环境是: Windows7_64bit + Python3.5_64bit + JDK1.8_64bit + +Jpype_0.5.52 (Python 和 JDK 的位数一定要相同)

  1. 安装 JPype: pip3.5 install JPype1-py3
  2. 找到 JRE 中的 jvm.dll 文件 (在 JDK 中的路径类似如下路径: F:/Java/jdk1.8.0_45/jre/bin/server/jvm.dll)

3. JPype 使用说明

1. 启动 JVM

JPype 提供的 startJVM() 函数的作用是启动 JAVA 虚拟机,所以在后续的任何 JAVA 代码被调用前,必须先调用此方法启动 JAVA 虚拟机。
jpype.startJVM() 的定义:
startJVM(jvm, *args)

3. 引用第三方 JAVA 扩展包

很多时候,在 python 项目中需要调用第三方的 Java 扩展包,这也是 JPype 的一个重要用途。
通过在 JVM 启动参数增加:-Djava.class.path = ext_classpath,实现在 Python 代码中调用已有的 Java 扩展包。
通过在 JVM 启动参数增加: -Djava.ext.dirs = ext_dirs , 实现在 Python 代码中引入 Java 扩展包的其他依赖包。

注意事项
当有其他依赖 JAR 包时,一定要使用-Djava.ext.dirs = ext_dirs 进行引入,否则在调用类对象时会报错:
jpype._jexception.ExceptionPyRaisable: java.lang.Exception: Class not found

2. 关闭 JVM

当使用完 JVM 后,可以通过 jpype.shutdownJVM() 来关闭 JVM,该函数没有输入参数。当 python 程序退出时,JVM 会自动关闭。

4. 实践

1. 直接调用 JAVA API

from jpype import *  
import os.path  
startJVM("F:/Java/jdk1.8.0_45/jre/bin/server/jvm.dll", "-ea")  
java.lang.System.out.println("hello World")  
shutdownJVM()

2. 调用 JAVA 第三方扩展包

JAR 包源代码为:

package com.test;

import org.apache.log4j.Logger;

public class MathDemo {
   public static Logger logger = Logger.getLogger(MathDemo.class.getName());
   public int add(int a, int b) {
     return a+b;
   }
}

将此源码打包编译为:MathDemo.jar,而 MathDemo.jar 又依赖 log4j-1.2.16.jar。

Python 脚本代码为:

from jpype import *
import jpype

jarpath = os.path.join(os.path.abspath('.'), 'F:/JPypeTestl/MathDemo.jar')
dependency = os.path.join(os.path.abspath('.'), 'F:/JPypeTestl/dependency')
jpype.startJVM("F:/Java/jdk1.8.0_45/jre/bin/server/jvm.dll", "-ea", "-Djava.class.path=%s" %jarpath,"-Djava.ext.dirs=%s" %dependency)    #当有依赖的JAR包存在时,一定要使用-Djava.ext.dirs参数进行引入
JClass = jpype.JClass('com.test.MathDemo')
instance = JClass()
result = (instance.add(10, 20)
print (result)
jpype.shutdownJVM()

5. 注意事项

在启动 JVM 的时候,默认不会把 JDK 中 “\jre\lib\ext” 扩展包下的 JAR 包引入,所以为了避免调用过程中出现问题,建议将 “\jre\lib\ext” 内的 JAR, 均放入我们自己的 "dependency" 目录,自行导入。
我在工作中就遇到过使用 JAVA 调用 JAR 成功,但是使用 JPypy 调用 JAR,缺乏 ext 扩展目录中 JAR 包的情况。


↙↙↙阅读原文可查看相关链接,并与作者交流