2017-06-02 70 views
0

我正在嘗試爲通過WebSocket向一系列客戶端廣播信息的服務器構建一個小型狀態監視器。爲此,我正在使用tornado.process.Subprocess以及/proc/目錄下的各種文件讀取幾個命令的輸出。我想知道如何異步地異步讀取不同命令的輸出,更新WebSocket通道將向客戶端廣播的值的字典。異步讀取Tornado中的多個文件

我嘗試使用gen.coroutineyield與陣列中的每個Subprocess調用返回的所有DummyFuture對象不幸無濟於事。這裏是我的代碼的簡化版本:

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) 

我想用的read_until_closecallback參數作爲一種解決方案,指派另一個回調參數get_data)當所有其他期貨成功解決那被稱爲的,但我發現該解決方案相當麻煩。

提前致謝!

+0

你也可以看看[run_on_executor](http://blog.trukhanov.net/Running-synchronous-code-on-tornado-asynchronously/)裝飾 – desertkun

回答

1

要從另一個協程中調用協程,您需要Python 3.5+中的「async def」和「await」,否則需要「gen.coroutine」和「yield」。下面是現代語法:

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.

欲瞭解更多信息,請參閱我的Refactoring Tornado CoroutinesTornado coroutine guide

+0

謝謝!這似乎做到了。以下是目前的實施情況,以供某人使用:https://github.com/martinarroyo/deployer/blob/standalone/monitor/statuscrawler.py#L33 – martinarroyo