這篇博客旨在吐血分享今天遇到的java調用python腳本遇到的坑,折騰了3個多小時終於能夠跑通了,代碼超級短,但網上的好多資料都是抄來抄去的,不多有可以直接跑通的,尤爲是針對你的python文件中用到第三方類庫的狀況。java
先來講說我爲何要用java調用python代碼,緣由就在於python在爬蟲方面提供了豐富的類庫,但我原本已經有一套java操做數據庫以及消息中間件的代碼,這些代碼用python實現的話可能須要至少一週時間,爲了減小時間成本,所以我決定用java調用python腳本的方式使用requests等等庫,下面把我解決的過程分享出來,但願能給遇到相似問題的朋友一點幫助。python
經過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
使用這種方式須要同時修改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