在一些复杂的应用场景中,脚本语言可能只是充当实现基础功能的模块,接受其它编程语言模块的“调遣”,在此,我以Java语言为例,介绍调用Python模块的方法。
编写一个Java程序,调用Python脚本TestMain.py,代码如下:
public static void main(String[] args) throws IOException, InterruptedException
{
// define the command string
String commandStr = new String(
"python D:\\Users\\workspace\\learn-python\\com\\demo\\TestMain.py");
//Create a Process instance and execute commands
Process pr = Runtime.getRuntime().exec(commandStr);
//Get the result produced by executing the above commands
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = null;
String result = "";
while ((line = in.readLine()) != null)
{
result += line + "\r\n";
}
System.out.println(result);
in.close();
int endFlag = pr.waitFor();
if (endFlag == 0)
{
System.out.println("The process is ended normally.");
}
}
TestMain.py中代码如下:
if __name__ == '__main__':
print('------------------------begin---------------------------')
print('just for testing!')
print('-------------------------end----------------------------')
运行结果:
【解释】:为什么运行的结果和直接运行Python脚本一样呢?
由于我们在Python脚本中,打印信息采用的是print函数,这是一个将信息打印到控制台或者终端的函数,在Process类的介绍中已经提及:Process进程实例(子进程)相对于调用它的Java进程(父进程)是父子关系,Process实例并没有自己的控制台或终端用于打印脚本执行的输出信息,可通过方法getInputStream()将输出重定向到调用脚本的父进程,进而输出。
通过这种机制,Java程序可以方便的调用Python脚本,并获得脚本执行的结果(脚本中须采用print打印调用方需要的结果)。
import sys
if __name__ == '__main__':
print('------------------------begin---------------------------')
#Get the parameter list
parameterList=sys.argv
print(parameterList)
print('-------------------------end----------------------------')
Java调用代码如下:
public static void main(String[] args) throws IOException, InterruptedException
{
// define the command string
String commandStr = new String(
"python D:\\Users\\workspace\\learn-python\\com\\demo\\TestMain.py param1 param2 param3");
//Create a Process instance and execute commands
Process pr = Runtime.getRuntime().exec(commandStr);
//Get the result produced by executing the above commands
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = null;
String result = "";
while ((line = in.readLine()) != null)
{
result += line + "\r\n";
}
System.out.println(result);
in.close();
int endFlag = pr.waitFor();
if (endFlag == 0)
{
System.out.println("The process is ended normally.");
}
}
执行Java代码输出Python脚本重定向打印的结果:
------------------------begin--------------------------- ['D:\\Users\\workspace\\learn-python\\com\\demo\\TestMain.py', 'param1', 'param2', 'param3'] ------------------------end--------------------------- The process is ended normally. |
很明显,Java调用时传递的参数被Python脚本正确接收,并根据空格分离开来,其中第一个为脚本名称,在实际应用中,我们通过sys.argv[1:]过滤掉第一个参数。
初步尝试了调用的快感,如果就此打住,显然是不明智的,继续探索更加复杂的调用。比如,我们需要同时传递,数字、字符串、列表参数:120 “commoncommands” listTemp[param1, param1, param1],并且要求参数的数量可变,怎么办呢?
其实很简单,传递的参数是以字符串的形式传递的,所有的参数都混在一个字符串中,我们只要接收字符串,并解析即可。在Python中,就有这么一个用于解析命令参数的函数:
def getopt(args, shortopts, longopts=[]): |
public static void main(String[] args) throws IOException, InterruptedException
{
// define the command string
String commandStr = new String(
"python D:\\Users\\workspace\\learn-python\\com\\demo\\TestMain.py -b Apple -l type1=common-log,type2=advance-log -t startTime=1502770332956,endTime=1502856732956");
//Create a Process instance and execute commands
Process pr = Runtime.getRuntime().exec(commandStr);
//Get the result produced by executing the above commands
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = null;
String result = "";
while ((line = in.readLine()) != null)
{
result += line + "\r\n";
}
System.out.println(result);
in.close();
pr.waitFor();
}
Python代码
import sys
import getopt
if __name__ == '__main__':
print('------------------------begin---------------------------')
#Get the parameter list
parameterList=sys.argv[1:]
#initialize all parameters
businessType=''
logType = {}
timeInfo = {}
opts, args = getopt.getopt(parameterList,"b:l:t:",['businessType=','logType=','timeInfo'])
for opt, arg in opts:
if opt in ("-b", "--businessType"):
businessType = arg
elif opt in ("-l", "--logType"):
logType = dict(item.split('=') for item in arg.split(','))
elif opt in ("-t", "--timeInfo"):
timeInfo = dict(item.split('=') for item in arg.split(','))
print('businessType:',businessType)
print('logType:',logType)
print('timeInfo:',timeInfo)
print('-------------------------end----------------------------')
运行结果: