在Tornado中异步读取多个文件

时间:2017-06-02 19:58:00

标签: python asynchronous tornado

我正在尝试为服务器构建一个微小的状态监视器,该服务器通过WebSocket向一系列客户端广播信息。为此,我正在使用tornado.process.Subprocess以及/proc/目录下的各种文件读取多个命令的输出。我想知道如何异步地异步读取不同命令的输出,更新WebSocket通道将向客户端广播的值字典。

我尝试使用gen.coroutineyield数组以及每个DummyFuture调用返回的所有Subprocess个对象,但遗憾的是无济于事。这是我的代码的简化版本:

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)

我想过使用callback的{​​{1}}参数作为解决方案,为read_until_close分配另一个回调参数,当所有其他期货成功解析时会调用,但我发现解决方案相当麻烦。

提前致谢!

1 个答案:

答案 0 :(得分:1)

要从另一个协同程序调用协同程序,您需要" async def"和#34;等待"在Python 3.5+中,或者" gen.coroutine"并且"收益"。这是现代语法:

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