java調用python


1.使用Runtime.getRuntime()執行腳本文件

該方法可以運行含有python第三方庫的程序

先建立python腳本文件 demo.py

import numpy as np a = np.arange(12).reshape(3,4) print(a) 

java調用python程序並輸出該結果

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Demo { public static void main(String[] args) { // TODO Auto-generated method stub Process proc; try { proc = Runtime.getRuntime().exec("python D:\\demo.py");// 執行py文件 //用輸入輸出流來截取結果 BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); String line = null; while ((line = in.readLine()) != null) { System.out.println(line); } in.close(); proc.waitFor(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } 

如若向python程序中函數傳遞參數並執行出結果,下面就舉一例來說明一下。
同樣建立python腳本文件demo2.py

import sys def func(a,b): return (a+b) if __name__ == '__main__': a = [] for i in range(1, len(sys.argv)): a.append((int(sys.argv[i]))) print(func(a[0],a[1])) 

其中sys.argv用於獲取參數url1,url2等。而sys.argv[0]代表python程序名,所以列表從1開始讀取參數。
以上代碼實現一個兩個數做加法的程序,下面看看在java中怎么傳遞函數參數,代碼如下:

int a = 18; int b = 23; try { String[] args = new String[] { "python", "D:\\demo2.py", String.valueOf(a), String.valueOf(b) }; Process proc = Runtime.getRuntime().exec(args);// 執行py文件 BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); String line = null; while ((line = in.readLine()) != null) { System.out.println(line); } in.close(); proc.waitFor(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } 

其中args是String[] { “python”,path,url1,url2 }; ,path是python程序所在的路徑,url1是參數1,url2是參數2,以此類推。

2. 將python腳本寫成進程為java提供服務

在java應用程序中調用python進程提供的服務。這種方法我認為是最好的!強推!!!python語言寫得程序畢竟還是在python環境中執行最有效率。而且python應用和java應用可以運行在不同的服務器上,通過進程的遠程訪問調用。更贊的是python運行環境還可以是虛擬環境,運行tensorflow模型神馬的完全沒問題!

python腳本文件如下:

import socket import sys import threading import numpy as np from PIL import Image def main(): # 創建服務器套接字 serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 獲取本地主機名稱 host = socket.gethostname() # 設置一個端口 port = 12345 # 將套接字與本地主機和端口綁定 serversocket.bind((host,port)) # 設置監聽最大連接數 serversocket.listen(5) # 獲取本地服務器的連接信息 myaddr = serversocket.getsockname() print("服務器地址:%s"%str(myaddr)) # 循環等待接受客戶端信息 while True: # 獲取一個客戶端連接 clientsocket,addr = serversocket.accept() print("連接地址:%s" % str(addr)) try: t = ServerThreading(clientsocket)#為每一個請求開啟一個處理線程 t.start() pass except Exception as identifier: print(identifier) pass pass serversocket.close() pass class ServerThreading(threading.Thread): # words = text2vec.load_lexicon() def __init__(self,clientsocket,recvsize=1024*1024,encoding="utf-8"): threading.Thread.__init__(self) self._socket = clientsocket self._recvsize = recvsize self._encoding = encoding pass def run(self): print("開啟線程.....") try: #接受數據 msg = '' while True: # 讀取recvsize個字節 rec = self._socket.recv(self._recvsize) # 解碼 msg += rec.decode(self._encoding) # 文本接受是否完畢,因為python socket不能自己判斷接收數據是否完畢, # 所以需要自定義協議標志數據接受完畢 if msg.strip().endswith('over'): msg=msg[:-4] break sendmsg = Image.open(msg) # 發送數據 self._socket.send(("%s"%sendmsg).encode(self._encoding)) pass except Exception as identifier: self._socket.send("500".encode(self._encoding)) print(identifier) pass finally: self._socket.close() print("任務結束.....") pass def __del__(self): pass if __name__ == "__main__": main() 

在java代碼中訪問python進程的代碼:

package hello; import java.lang.System; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.Socket; import java.io.OutputStream; import java.io.PrintStream; import java.io.InputStream; public class hello { public static void main(String[] args){ //System.out.println("Hello World!"); // TODO Auto-generated method stub try { InetAddress addr = InetAddress.getLocalHost(); String host=addr.getHostName(); //String ip=addr.getHostAddress().toString(); //獲取本機ip //log.info("調用遠程接口:host=>"+ip+",port=>"+12345); // 初始化套接字,設置訪問服務的主機和進程端口號,HOST是訪問python進程的主機名稱,可以是IP地址或者域名,PORT是python進程綁定的端口號 Socket socket = new Socket(host,12345); // 獲取輸出流對象 OutputStream os = socket.getOutputStream(); PrintStream out = new PrintStream(os); // 發送內容 out.print( "F:\\xxx\\0000.jpg"); // 告訴服務進程,內容發送完畢,可以開始處理 out.print("over"); // 獲取服務進程的輸入流 InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8")); String tmp = null; StringBuilder sb = new StringBuilder(); // 讀取內容 while((tmp=br.readLine())!=null) sb.append(tmp).append('\n'); System.out.print(sb); // 解析結果 //JSONArray res = JSON.parseArray(sb.toString()); } catch (IOException e) { e.printStackTrace(); }finally { try {if(socket!=null) socket.close();} catch (IOException e) {} System.out.print("遠程接口調用結束."); } } }


如何使用Java調用Python程序
本文為大家介紹如何java調用python方法,供大家參考。
實際工程項目中可能會用到Java和python兩種語言結合進行,這樣就會涉及到一個問題,就是怎么用Java程序來調用已經寫好的python腳本呢,一共有三種方法可以實現,具體方法分別為大家介紹:
1. 在java類中直接執行python語句

此方法需要引用 org.python包,需要下載Jpython。在這里先介紹一下Jpython。下面引入百科的解釋:

  • Jython是一種完整的語言,而不是一個Java翻譯器或僅僅是一個Python編譯器,它是一個Python語言在Java中的完全實現。Jython也有很多從CPython中繼承的模塊庫。最有趣的事情是Jython不像CPython或其他任何高級語言,它提供了對其實現語言的一切存取。所以Jython不僅給你提供了Python的庫,同時也提供了所有的Java類。這使其有一個巨大的資源庫。
 
這里我建議下載最新版本的Jpython,因為可以使用的python函數庫會比老版本的多些,目前最新版本為2.7。
下載jar包請點擊 Download Jython 2.7.0 - Standalone Jar
下載安裝程序請點擊 Download Jython 2.7.0 - Installer
如果使用maven依賴添加的話,使用下面的語句
  1.  
    <dependency>
  2.  
    <groupId>org.python</groupId>
  3.  
    <artifactId>jython-standalone</artifactId>
  4.  
    <version> 2.7.0</version>
  5.  
    </dependency>
以上准備好了,就可以直接在java類中寫python語句了,具體代碼如下:
  1.  
    PythonInterpreter interpreter = new PythonInterpreter();
  2.  
    interpreter.exec( "a=[5,2,3,9,4,0]; ");
  3.  
    interpreter.exec( "print(sorted(a));"); //此處python語句是3.x版本的語法
  4.  
    interpreter.exec( "print sorted(a);"); //此處是python語句是2.x版本的語法

 

輸出結果如下:
這里會看到輸出的結果都是一樣的,也就是說Jpython兼容python2.x和3.x版本的語句,運行速度會比直接運行python程序稍慢一點。
但是每次運行結果都會提示console: Failed to install ”: java.nio.charset.UnsupportedCharsetException: cp0. 這樣看起來很煩,因為每次運行結果都會出現紅色的提示語句,以為是錯誤,程序員應該都不願意看到這一幕,得想個辦法解決。
解決方法如下:
在要執行的代碼上右鍵, Run As>Run Configurations,選擇第二個頁簽Arguments,在VM arguments中添加以下語句
-Dpython.console.encoding=UTF-8
然后Apply->Run就可以了。
如下圖所示:

 

 

 

 

2. 在java中調用本地python腳本
首先在本地建立一個python腳本,命名為add.py,寫了一個簡單的兩個數做加法的函數,代碼如下:
  1.  
    def add(a,b):
  2.  
    return a + b

 python的功能函數已經寫好,接下來我們寫一個java的測試類(同樣需要用到Jpython包),來測試一下是否可以運行成功。代碼如下:

  1.  
    import org.python.core.PyFunction;
  2.  
    import org.python.core.PyInteger;
  3.  
    import org.python.core.PyObject;
  4.  
    import org.python.util.PythonInterpreter;
  5.  
     
  6.  
    public class Java_Python_test {
  7.  
     
  8.  
    public static void main(String[] args) {
  9.  
    // TODO Auto-generated method stub
  10.  
    PythonInterpreter interpreter = new PythonInterpreter();
  11.  
    interpreter.execfile( "D:\\add.py");
  12.  
     
  13.  
    // 第一個參數為期望獲得的函數(變量)的名字,第二個參數為期望返回的對象類型
  14.  
    PyFunction pyFunction = interpreter.get("add", PyFunction.class);
  15.  
    int a = 5, b = 10;
  16.  
    //調用函數,如果函數需要參數,在Java中必須先將參數轉化為對應的“Python類型”
  17.  
    PyObject pyobj = pyFunction.__call__(new PyInteger(a), new PyInteger(b));
  18.  
    System.out.println( "the anwser is: " + pyobj);
  19.  
    }
  20.  
    }

 

運行結果如圖所示:

OK,測試成功了~

關於Jpython更多詳細的信息可以參考官方的相關文檔,官網地址點這里

 

 

注意:以上兩個方法雖然都可以調用python程序,但是使用Jpython調用的python庫不是很多,如果你用以上兩個方法調用,而python的程序中使用到第三方庫,這時就會報錯java ImportError: No module named xxx。遇到這種情況推薦使用下面的方法,即可解決該問題。

3. 使用Runtime.getRuntime()執行腳本文件(推薦)

 

 

為了驗證該方法可以運行含有python第三方庫的程序,我們先寫一個簡單的python腳本,代碼如下:
  1.  
    import numpy as np
  2.  
     
  3.  
    a = np.arange( 12).reshape(3,4)
  4.  
    print(a)

 

 

可以看到程序中用到了numpy第三方庫,並初始化了一個3×4的一個矩陣。
下面來看看怎么用Runtime.getRuntime()方法來調用python程序並輸出該結果,java代碼如下:
  1.  
    import java.io.BufferedReader;
  2.  
    import java.io.IOException;
  3.  
    import java.io.InputStreamReader;
  4.  
     
  5.  
    public class Demo1 {
  6.  
     
  7.  
    public static void main(String[] args) {
  8.  
    // TODO Auto-generated method stub
  9.  
    Process proc;
  10.  
    try {
  11.  
    proc = Runtime.getRuntime(). exec("python D:\\demo1.py");// 執行py文件
  12.  
    //用輸入輸出流來截取結果
  13.  
    BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
  14.  
    String line = null;
  15.  
    while ((line = in.readLine()) != null) {
  16.  
    System.out.println(line);
  17.  
    }
  18.  
    in.close();
  19.  
    proc.waitFor();
  20.  
    } catch (IOException e) {
  21.  
    e.printStackTrace();
  22.  
    } catch (InterruptedException e) {
  23.  
    e.printStackTrace();
  24.  
    }
  25.  
    }
  26.  
    }

 

 

輸出的結果如下圖所示:

 

 

可以看到運行成功了,但有的朋友可能會問了,怎么在python程序中函數傳遞參數並執行出結果,下面我就舉一例來說明一下。
先寫一個python的程序,代碼如下:
  1.  
    import sys
  2.  
     
  3.  
    def func(a,b):
  4.  
    return (a+b)
  5.  
     
  6.  
    if __name__ == '__main__':
  7.  
    a = []
  8.  
    for i in range(1, len(sys.argv)):
  9.  
    a.append(( int(sys.argv[i])))
  10.  
     
  11.  
    print(func(a[0],a[1]))

 

 

其中sys.argv用於獲取參數url1,url2等。而sys.argv[0]代表python程序名,所以列表從1開始讀取參數。
以上代碼實現一個兩個數做加法的程序,下面看看在java中怎么傳遞函數參數,代碼如下:
  1.  
    int a = 18;
  2.  
    int b = 23;
  3.  
    try {
  4.  
    String[] args = new String[] { "python", "D:\\demo2.py", String.valueOf(a), String.valueOf(b) };
  5.  
    Process proc = Runtime.getRuntime().exec(args1);// 執行py文件
  6.  
     
  7.  
    BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
  8.  
    String line = null;
  9.  
    while ((line = in.readLine()) != null) {
  10.  
    System.out.println(line);
  11.  
    }
  12.  
    in.close();
  13.  
    proc.waitFor();
  14.  
    } catch (IOException e) {
  15.  
    e.printStackTrace();
  16.  
    } catch (InterruptedException e) {
  17.  
    e.printStackTrace();
  18.  
    }

 

 

其中args是String[] { “python”,path,url1,url2 }; ,path是python程序所在的路徑,url1是參數1,url2是參數2,以此類推。
最后結果如圖所示:

 

 


OK,成功了。

 

 

 
最后補充一點:

本人電腦上由於同時存在兩個python,而我不想用默認的那個,也不想修改默認的python解釋器,這種情況下,可以寫一個bat文件,在bat文件中通過dos命令切換到該python所在目錄,然后運行py文件(py文件要放在該目錄下)

下面附上程序:

bat文件:

  1.  
    @echo off
  2.  
    C:
  3.  
    cd C:\Anaconda2\envs\py3
  4.  
    start python test.py
  5.  
    exit

java程序:

  1.  
    import java.io.BufferedReader;
  2.  
    import java.io.IOException;
  3.  
    import java.io.InputStreamReader;
  4.  
     
  5.  
    public class Demo1 {
  6.  
     
  7.  
    public static void main(String[] args) {
  8.  
    // TODO Auto-generated method stub
  9.  
    Process proc;
  10.  
    try {
  11.  
    proc = Runtime.getRuntime().exec( "cmd /c E:\\Faultdetection\\fault1\\run.bat");// 執行py文件
  12.  
    //用輸入輸出流來截取結果
  13.  
    BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
  14.  
    String line = null;
  15.  
    while ((line = in.readLine()) != null) {
  16.  
    System.out.println(line);
  17.  
    }
  18.  
    in.close();
  19.  
    proc.waitFor();
  20.  
    } catch (IOException e) {
  21.  
    e.printStackTrace();
  22.  
    } catch (InterruptedException e) {
  23.  
    e.printStackTrace();
  24.  
    }
  25.  
    }
  26.  
    }

 


免責聲明!

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



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