2016-06-21 69 views
2

我寫了2個名爲runner.py和connect.py的python腳本。 跑步者腳本使用特定端口啓動流量模擬,另一人連接並能夠發送命令。這兩個腳本在我的Python IDE中工作正常。但是我想從java啓動兩個腳本來接收數據。(Jython)從java運行python腳本的問題

import org.python.core.PyInstance; 
import org.python.util.PythonInterpreter; 
import org.python.core.PyObject; 
import org.python.core.PyString; 

public class PythonHandler { 

    PythonInterpreter interpreter = null; 
    String script_dir; 

    public PythonHandler() { 
     PythonInterpreter.initialize(System.getProperties(), System.getProperties(), new String[0]); 

     this.interpreter = new PythonInterpreter(); 
     this.script_dir = System.getProperty("user.dir"); 
    } 

    void execfile(final String fileName) { 
     this.interpreter.execfile(fileName); 
    } 

    PyInstance createClass(final String className, final String opts) { 
     return (PyInstance) this.interpreter.eval(className + "(" + opts + ")"); 
    } 

    /** 
    * This method will start the python script runner.py 
    * NOTE: doesn't work if there is not a main method in the python script 
    */ 
    public void startRunner() { 
     String runner_dir = script_dir + "\\src\\de\\uniol\\inf\\is\\odysseus\\pgtaxi\\traci\\traci4python\\runner.py"; 
     PythonHandler ie = new PythonHandler(); 
     ie.execfile(runner_dir); 
    } 

    /** 
    * This method will start the python script connect.py 
    * NOTE: doesn't work if there is not a main method in the python script 
    */ 
    public void startConnect() { 
     String connect_dir = script_dir 
       + "\\src\\de\\uniol\\inf\\is\\odysseus\\pgtaxi\\traci\\traci4python\\connect.py"; 
     PythonHandler ie = new PythonHandler(); 
     ie.execfile(connect_dir); 
    } 

    /** 
    * This method will start the python script connect.py 
    * If there is not a main method you can run a specific function 
    * 
    * @param function 
    *   name of the function you want to start 
    */ 
    public void callConnectFunction(String function) { 
     String connect_dir = script_dir 
       + "\\src\\de\\uniol\\inf\\is\\odysseus\\pgtaxi\\traci\\traci4python\\connect.py"; 
     PythonHandler ie = new PythonHandler(); 
     ie.execfile(connect_dir); 
     PyInstance run = ie.createClass("Connection", "None"); 
     run.invoke(function); 
    } 

    /** 
    * This method will start the python script runner.py 
    * If there is not a main method you can run a specific function 
    * 
    * @param function 
    *   name of the function you want to start 
    */ 
    public void callRunnerFunction(String function) { 
     String runner_dir = script_dir + "\\src\\de\\uniol\\inf\\is\\odysseus\\pgtaxi\\traci\\traci4python\\connect.py"; 
     PythonHandler ie = new PythonHandler(); 
     ie.execfile(runner_dir); 
     PyInstance run = ie.createClass("Runner", "None"); 
     run.invoke(function); 
    } 
} 

這兩個腳本都會啓動,但在connect.py中會發生錯誤。我不明白爲什麼我能夠從python IDE運行腳本,但不能從我的java代碼運行腳本。 下面是從Python腳本代碼:

runner.py

import sys 
import subprocess 
import os 

PORT = 8873 

class Runner: 
__gui = None 

def __init__(self, gui): 
    self.__gui = gui 
    print "Starting runner..." 

def runLocal(self): 
    sumoBinary = os.path.abspath(os.curdir) 
    sumoBinary = sumoBinary.split('de.uniol.inf.is.odysseus.pgtaxi')[0] 
    sumoBinary = sumoBinary + 'de.uniol.inf.is.odysseus.pgtaxi\\sumo\\bin\\sumo-gui' 
    scenario = os.path.abspath(os.curdir) 
    scenario = sumoBinary.split('de.uniol.inf.is.odysseus.pgtaxi')[0] 
    scenario = scenario + 'de.uniol.inf.is.odysseus.pgtaxi\\scenario\\oldenburg.sumocfg' 
    sumoProcess = subprocess.Popen([sumoBinary, "-c", scenario, "--remote-port", str(PORT)], stdout=sys.stdout, stderr=sys.stderr) 

if __name__ == '__main__': 
conn = Runner('None') 
conn.runLocal() 

connect.py

import sys 
import os 

PORT = 8873 

class Connection: 
__gui = None 

def __init__(self, gui): 
    self.__gui = gui 
    print "Starting connect..." 

def initTraci(self): 
    tools = os.path.abspath(os.curdir) 
    tools = tools.split('de.uniol.inf.is.odysseus.pgtaxi')[0] 
    tools = tools + 'de.uniol.inf.is.odysseus.pgtaxi\\sumo\\tools' 
    sys.path.append(tools) 
    import traci 
    traci.init(PORT) 
    step = 0 
    while step < 1000: 
     traci.simulationStep() 
     step += 1 

    traci.close() 
    sys.stdout.flush() 

def getFreePort(self): 
    tools = os.path.abspath(os.curdir) 
    tools = tools.split('de.uniol.inf.is.odysseus.pgtaxi')[0] 
    tools = tools + 'de.uniol.inf.is.odysseus.pgtaxi\\sumo\\tools' 
    sys.path.append(tools) 
    import sumolib 
    PORT = sumolib.miscutils.getFreeSocketPort() 

if __name__ == '__main__': 
conn = Connection('None') 
conn.initTraci() 

我得到這個異常:

Exception in thread "MainThread" Traceback (most recent call last): 
    File "C:\Users\FEPREUSS\Desktop\PG\workspace\de.uniol.inf.is.odysseus.pgtaxi\src\de\uniol\inf\is\odysseus\pgtaxi\traci\traci4python\connect.py", line 44, in <module> 
    conn.initTraci() 
    File "C:\Users\FEPREUSS\Desktop\PG\workspace\de.uniol.inf.is.odysseus.pgtaxi\src\de\uniol\inf\is\odysseus\pgtaxi\traci\traci4python\connect.py", line 25, in initTraci 
    traci.init(PORT) 
    File "C:\Users\FEPREUSS\Desktop\PG\workspace\de.uniol.inf.is.odysseus.pgtaxi\sumo\tools\traci\__init__.py", line 65, in init 
    return getVersion() 
    File "C:\Users\FEPREUSS\Desktop\PG\workspace\de.uniol.inf.is.odysseus.pgtaxi\sumo\tools\traci\__init__.py", line 82, in getVersion 
    return _connections[""].getVersion() 
AttributeError: 'NoneType' object has no attribute 'getVersion' 

而且,這兩個方法來自導致脫離的lib:

def init(port=8813, numRetries=10, host="localhost", label="default"): 
    """ 
    Establish a connection to a TraCI-Server and store it under the given 
    label. This method is not thread-safe. It accesses the connection 
    pool concurrently. 
    """ 
    _connections[label] = connect(port, numRetries, host) 
    switch(label) 
    return getVersion() 

def getVersion(): 
    return _connections[""].getVersion() 

希望有人能幫助我。

+0

錯誤消息指示與SUMO的連接失敗。這是一個令人困惑的信息,已經有一張票可以解決這個http://sumo.dlr.de/trac.wsgi/ticket/2444。你可以添加你對問題所做的精確的jython調用,並檢查相撲是否真的由runner.py啓動(顯示在進程列表中)。 – Michael

+0

我添加了jython連接的完整類。相撲真的開始了。另外我試圖連接到一個服務器上運行的相撲應用程序,我得到了相同的錯誤信息。 –

+0

當您嘗試連接時,您如何確保相撲已經啓動並正在聆聽?你有沒有在延遲後嘗試連接? – Michael

回答

0

您偶然發現了一個jython bug,它被SUMO隱藏了失敗套接字連接的錯誤消息。不幸的是你不能繞過它容易除了在第49行

編輯SUMO /工具/崔西/ connection.py只是

self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) 

一種解決方法是致力於SUMO倉庫以及更換self._socket = socket()

+0

非常感謝。 Sumo團隊的支持非常棒。 :) –