java/linux执行Python脚本

工作原因,需要通过Python脚本进行接口访问获取接口数据。

分析

网上java执行Python脚本无外乎三种方法:
1、直接执行Python脚本代码
  引用 org.python包

PythonInterpreter interpreter = new     PythonInterpreter();    
    interpreter.exec("days=('mod','Tue','Wed','Thu','Fri','Sat','Sun'); ");   
    ///执行python脚本

2、执行python .py文件

PythonInterpreter interpreter = new PythonInterpreter();    
InputStream filepy = new FileInputStream("D:\\demo.py");   
interpreter.execfile(filepy);  ///执行python py文件  
filepy.close();  

3、使用Runtime.getRuntime()执行脚本文件
这种方式和.net下面调用cmd执行命令的方式类似。如果执行的python脚本有引用第三方包的,建议使用此种方式。使用上面两种方式会报错Java ImportError: No module named arcpy。

Process proc = Runtime.getRuntime().exec("python  D:\\demo.py");    
proc.waitFor(); 

引用:http://blog.csdn.net/l1028386804/article/details/50914261


工程

本次项目使用了Runtime.getRuntime().exec()方法,解决Python的执行问题,原因如下:
1、此方法使用的系统命令执行,window下使用cmd命令,linux环境下使用Python命令。没有使用第三方依赖包,功能齐全、方便管理。
2、系统环境下对Python环境的支持最大,如引入的第三方包python、jpython等,可能对类库的支持不是很好,在引入基础类库的时候就得不到很好的支持,引起异常报错。

代码如下:

public List<String> python(String pythonPath) {
        List<String> res = new ArrayList<>();
        String url=PythonRunner.class.getClassLoader().getResource("").getPath()+"cfg/spring/cs.py";
        logger.info("脚本地址:"+url);
        File file = new File(url);
        if (!file.exists()){
            res.add("python脚本不存在!");
            return res;
        }
        String [] cmd={"python",url};
        try {
            logger.info("开始执行脚本...\n");
            Process process = Runtime.getRuntime().exec(cmd);
            if (process == null) {
                return null;
            }
            Scanner scanner = new Scanner(process.getInputStream());
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                res.add(line);
            }

            try {
                process.waitFor();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            logger.info("脚本执行结束...\n 本次查询数据"+res.size()+"条");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;
    }

上面的程序经过了调试,可以正常获取到Python脚本执行输出的信息并在java程序里面进行处理。
命令执行采用的是
public Process exec(String [] cmdArray)
其中 amdArray 是命令数组,如
String [] cmd={"python",url};
其实就是linux环境下的Python执行命令:
python ../vip/cs.py


至于cs.py 可以简单写个Python脚本测试下,如下实例:

#!/usr/bin/env python
# By: Kelcey Damage, 2012 & Kraig Amador, 2012
str ='1123'
print str

测试结果

1123


问题

不过在Python脚本执行输出后,如果对输出的内容进行转化在输出,例如转成json格式后print,java程序里面的Process好像不能正常获取到转换之后的信息流。如:

from api import json
json=json.dumps(all_vms, ensure_ascii=False, indent=2)
print json

该Process获取的结果为空。
问题原因可能是因为Process获取内存流,而通过json工具类转化后已经在脚本里面把原始流处理接收了,因此导致Process接收的为空。本分析只是猜测,具体还未验证。不过暂时不影响项目开发,先记录下来吧。


文件读写

为记录日志,还用到了文件写入:

#p = open("/home/print.txt", 'w+')
#print >>p,json.dumps(all_vms).decode('utf8').encode('gbk')

这个方法还解决了中文乱码的问题,也记录一下。

Logo

更多推荐