(轉)java調用python腳本

這篇博客旨在吐血分享今天遇到的java調用python腳本遇到的坑,折騰了3個多小時終於能夠跑通了,代碼超級短,但網上的好多資料都是抄來抄去的,不多有可以直接跑通的,尤爲是針對你的python文件中用到第三方類庫的狀況。java

先來講說我爲何要用java調用python代碼,緣由就在於python在爬蟲方面提供了豐富的類庫,但我原本已經有一套java操做數據庫以及消息中間件的代碼,這些代碼用python實現的話可能須要至少一週時間,爲了減小時間成本,所以我決定用java調用python腳本的方式使用requests等等庫,下面把我解決的過程分享出來,但願能給遇到相似問題的朋友一點幫助。python

常見的java調用python腳本方式

  • 經過jython.jar提供的類庫實現
  • 經過Runtime.getRuntime()開啓進程來執行腳本文件

經過jython.jar提供的類庫實現

經過jython.jar實現的話,咱們須要引入jar包,具體我寫了一個demo,假設你的python代碼爲test.py:數據庫

def my_test(name, age):
    print("name: "+name)
    print("age: "+age)
    return "success"

java調用test.py代碼:ruby

public static void main(String[] args) {
      PythonInterpreter interpreter = new PythonInterpreter();  
      interpreter.execfile("E:\\workspace\\pycharm_workspace\\weixincrawer\\test.py");  
      PyFunction function = (PyFunction)interpreter.get("my_test",PyFunction.class);  
      PyObject pyobject = function.__call__(new PyString("huzhiwei"),new PyString("25")); 
      System.out.println("anwser = " + pyobject.toString());  
    }

輸出結果:ide

name: huzhiwei age: 25 anwser = success

到此是沒有什麼問題的,咱們使用function.call方法傳入參數調用python函數,使用pyobject.toString()方法拿到python中my_test函數的返回值,可是若是你把test.py稍微作下修改以下:函數

import requests

def my_test(name, age):
    response = requests.get("http://www.baidu.com")
    print("name: "+name)
    print("age: "+age)
    return "success"

不修改java調用代碼的狀況下,你會獲得下面異常信息:url

ImportError: No module named requests

沒錯,這就是我要討論的問題,由於jython不可能涵蓋全部python第三方類庫的東西,因此在咱們得python文件中用到requests類庫的時候,很顯然會報找不到模塊的錯誤,這個時候咱們是能夠經過Runtime.getRuntime()開啓進程來執行python腳本文件的。spa

經過Runtime.getRuntime()開啓進程來執行腳本文件

使用這種方式須要同時修改python文件以及java調用代碼,在此我一樣在上面test.py的基礎上進行修改:.net

import requests
import sys

def my_test(name, age):
    response = requests.get("http://www.baidu.com")
    print("url:"+response.url)
    print("name: "+name)
    print("age: "+age)
    return "success"

my_test(sys.argv[1], sys.argv[2])

和上面test.py代碼最大的區別在於,咱們此處開啓進程的方式其實是在隱形的調用dos界面進行操做,所以在python代碼中咱們須要經過sys.argv的方式來拿到java代碼中傳遞過來的參數。rest

java調用代碼部分:

public static void main(String[] args) {
      String[] arguments = new String[] {"python", "E:\\workspace\\pycharm_workspace\\weixincrawer\\test.py", "huzhiwei", "25"};
        try {
            Process process = Runtime.getRuntime().exec(arguments);
            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = null;  
          while ((line = in.readLine()) != null) {  
              System.out.println(line);  
          }  
          in.close();  
          int re = process.waitFor();  
          System.out.println(re);
        } catch (Exception e) {
            e.printStackTrace();
        }  
    }

結果輸出:

url:http://www.baidu.com/ name: huzhiwei age: 25 0

在此須要注意的一點,java代碼中的process.waitFor()返回值爲0表示咱們調用python腳本成功,返回值爲1表示調用python腳本失敗,這和咱們一般意義上見到的0與1定義正好相反。

個人代碼:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2018-02-27
# @Author  : zhangmingcheng

from PIL import Image
import imagehash
import sys

def get_hash(path):
    image = Image.open(path)
    h = str(imagehash.dhash(image))
    print h
    return h 

get_hash(sys.argv[1])

java

/**
	 * 獲取影像dhash,獲取完後將影像刪除
	 */
	@Override
	public String getDhash(String absolutePathName) {
		String dhash = "";
		String[] arguments = new String[] { "python", "/root/imagedhash/rest.py", absolutePathName };
		try {
			Process process = Runtime.getRuntime().exec(arguments);
			BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
			String line = null;
			while ((line = in.readLine()) != null) {
				dhash = line;
			}
			in.close();
			process.waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		}
		File file = new File(absolutePathName);
		if (file.exists() && file.isFile()) {
			file.delete();
			System.out.println(absolutePathName + "影像的dhash值=" + dhash + ",刪除影像成功");
		}
		return dhash;
	}

轉自:http://blog.csdn.net/hzw19920329/article/details/77509497

相關文章
相關標籤/搜索