1. 程式人生 > >JAVA web呼叫執行python指令碼程式的四種方式,迴避java.lang.OutOfMemoryError:PermGen space記憶體溢位問題

JAVA web呼叫執行python指令碼程式的四種方式,迴避java.lang.OutOfMemoryError:PermGen space記憶體溢位問題

我在網上搜到的JAVA呼叫python程式的三種方式:

方式一:呼叫python函式。可以傳入引數,獲取返回值。

                      public static void PythonFunctionTest(){
                        //python 直譯器
                        PythonInterpreter  interpreter = new PythonInterpreter();  
                        interpreter.execfile("E:\\Python_code\\helloPython.py");
                        PyFunction func=(PyFunction)interpreter.get("adder", PyFunction.class);
            
                        int a=2010;
                       int b=2;
                       PyObject pyobj = func.__call__(new PyInteger(a), new PyInteger(b));  
                       System.out.println("answer= "+pyobj.toString());
                     }
方式二:直接執行python指令碼。不能傳參,不能獲取返回值。
                 public static void PythonTextTest()
                {
                   PythonInterpreter  interpreter = new PythonInterpreter();  
                   interpreter.execfile("E:/Python_code/helloPython1.py");
                }

方式三:在JAVA程式碼裡面直接寫python程式,直接執行。這種方法顯然可以把引數傳進去,但是能不能獲得返回值需要進一步研究。
                 public static void PythonTest(){
                   PythonInterpreter interpreter =new PythonInterpreter();
                   interpreter.exec("days=('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday')");
                   interpreter.exec("print days[0]");
                }
考慮了一下,因為第一種方式可以以呼叫函式的形式,同時即可以傳參又可以獲取返回值,所以我選擇了第一種方式用於在JAVA程式碼塊中執行python程式。我在單獨的一個JAVA程式中執行相應程式碼時,沒有問題,可以傳參也可以獲得返回的結果。但是當我把這段程式碼放到現有的JAVAWEB的程式中時,會出現

java.lang.OutOfMemoryError:PermGen space記憶體溢位的問題。


於是我又按照網上的方法增到tomcat和eclipse的記憶體,結果無效。就這樣卡了很久後,我找到了第四種執行python程式的方法,這個方法不會產生記憶體溢位的問題。

方式四:使用控制檯執行python指令碼,可以傳參和獲取返回值。

               public static String runTimeMethod(String name,String path) {
               try {
                    String cmd="python E:\\Python_code\\settingTest.py "+name+" "+path;
                    Process pr = Runtime.getRuntime().exec(cmd);
                    BufferedReader in = new BufferedReader(new InputStreamReader(
                    pr.getInputStream()));
                    String line="";
//輸出列印在控制檯上的結果            
//                  while ((line = in.readLine()) != null) {
//                  System.out.println(line);
//                 }
//得到列印在控制檯上的結果
                    while ((line = in.readLine()) != null) {
                    result+=line;
                   }
                   in.close();
                   pr.waitFor();
//                 System.out.println("end");
                   } catch (Exception e) {
                   e.printStackTrace();
                 }
                return result;
    }
其實這種方法就是在JAVA程式中執行控制檯命令,其效果等同於把
python E:\\Python_code\\settingTest.py  arg1 arg2
這段命令拷貝到cmd控制檯中。

雖然可以傳入引數或獲取返回值,但其實它的實現並不是特別靈活和好用。下面是我用於測試的python程式碼。

#coding=utf-8
import json
import sys
def JsonTestForDownloadApks(name,path):
    print name,'   ',path 
name=sys.argv[1]
path=sys.argv[2]
JsonTestForDownloadApks(name,path)
可以看出,傳入引數的實現是通過python程式獲取控制檯輸入的方式。sys.arg[0]是當前python程式的執行路徑,sys.arg[1],sys.arg[2]是我們輸入的第一,二個引數。獲取返回結果是通過獲取列印到控制檯的輸出流獲的方式。其實這種方式有很大的侷限性,但是它起碼能迴避讓我頭疼的記憶體溢位問題,也能滿足我目前的功能需求,所以我選擇了這種方式。

PS.因為我對python的知識幾乎一無所知,對於python和JAVA之間的呼叫也是現學現用,所以我上面所說的方法可能非常低階甚至存在很大的風險,僅供大家參考。