2017-06-02 3 views
0

Ich versuche, einen winzigen Statusmonitor für einen Server zu erstellen, der die Informationen über einen WebSocket an eine Reihe von Clients sendet. Zu diesem Zweck lese ich die Ausgabe mehrerer Befehle unter Verwendung von tornado.process.Subprocess sowie verschiedener Dateien unter dem Verzeichnis /proc/. Ich würde gerne wissen, wie ich asynchron die Ausgabe der verschiedenen Befehle asynchron lesen kann, indem ich das Wörterbuch der Werte aktualisiere, die die WebSocket-Kanäle an die Clients senden.Asynchrones Lesen mehrerer Dateien in Tornado

Ich versuchte gen.coroutine und yield ing ein Array mit allen DummyFuture Objekte, die jeweils Subprocess Aufruf zurückkehrt verwenden, leider ohne Erfolg. Hier ist eine vereinfachte Version von meinem Code:

def get_data(*args, **kwargs): 
    response_dict = {} 
    fd_uname = process.Subprocess("uname -r", shell=True, stdout=process.Subprocess.STREAM).stdout 

    f_uname = fd_uname.read_until_close() # A DummyFuture is generated 
    fd_uptime = process.Subprocess("uptime | tail -n 1 | awk '{print $3 $4 $5}'", shell=True, stdout=subprocess.PIPE).stdout 
    f_uptime.read_until_close() 

    # In the end, the results will be stored as entries of response_dict 

data_dict = {} 
def process_data(): 
    result = get_data() # The goal is to run this function asynchronously 
    data_dict = result 

open_ws = set() 
class WebSocketIndexHandler(websocket.WebSocketHandler): 
    def open(self): 
     open_ws.add(self) 
     self.callback = PeriodicCallback(self.send_data, 1000) 
     self.callback.start() 
     start_callback() 

    def send_data(self): 
     self.write_message(data_dict) 

    def on_close(self): 
     self.callback.stop() 
     open_ws.remove(self) 

ProcessCallback(get_data, 1000) 

ich daran gedacht, mit dem callback Parameter von read_until_close als Lösung, die Zuweisung einer anderen Rückrufparameter zu get_data), die aufgerufen werden würde, wenn alle anderen Futures erfolgreich lösen, aber ich finde Diese Lösung ist ziemlich umständlich.

Vielen Dank im Voraus!

+0

Sie können auch auf [run_on_executor] (http://blog.trukhanov.net/Running-synchronous-code-on-tornado-asynchronously/) Dekorateur – desertkun

Antwort

1

Um eine Coroutine aus einer anderen Coroutine aufzurufen, benötigen Sie entweder "async def" und "await" in Python 3.5+ oder "gen.coroutine" und "yield". Hier ist die moderne Syntax:

async def get_data(*args, **kwargs): 
    response_dict = {} 
    fd_uname = process.Subprocess("uname -r", shell=True, stdout=process.Subprocess.STREAM).stdout 

    uname_result = await fd_uname.read_until_close() 
    fd_uptime = process.Subprocess("uptime | tail -n 1 | awk '{print $3 $4 $5}'", shell=True, stdout=subprocess.PIPE).stdout 
    uptime_result = await f_uptime.read_until_close() 

    # In the end, the results will be stored as entries of response_dict 
    return response_dict 

async def process_data(): 
    result = await get_data() # The goal is to run this function asynchronously 
    # Now do something with the result.... 

Make sure you import subprocess from tornado, of course, not from the standard library.

Weitere Informationen finden Sie in der meine Refactoring Tornado Coroutines oder die Tornado coroutine guide.

+0

Vielen Dank! Das schien es zu tun. Hier ist die aktuelle Implementierung, falls sie für jemanden nützlich ist: https://github.com/martinarroyo/deployer/blob/standalone/monitor/statuscrawler.py#L33 – martinarroyo

Verwandte Themen