(轉)java調用python腳本


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

先來說說我為什么要用java調用python代碼,原因就在於python在爬蟲方面提供了豐富的類庫,但我本來已經有一套java操作數據庫以及消息中間件的代碼,這些代碼用python實現的話可能需要至少一周時間,為了減少時間成本,因此我決定用java調用python腳本的方式使用requests等等庫,下面把我解決的過程分享出來,希望能給遇到類似問題的朋友一點幫助。

常見的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代碼:

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());  
    }

輸出結果:

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調用代碼的情況下,你會得到下面異常信息:

ImportError: No module named requests

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

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

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

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代碼中傳遞過來的參數。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM