Tornado 异步读取多个文件

Asynchronous reading of multiple files in Tornado

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

我尝试使用 gen.coroutineyield 数组,其中包含每个 Subprocess 调用 returns 的所有 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   }'", 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),当所有其他期货成功解析时将被调用,但我发现该解决方案相当麻烦。

提前致谢!

要从另一个协程调用协程,您需要 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   }'", 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 Coroutines or the Tornado coroutine guide