2017-06-02 27 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