如何在龙卷风中以无阻塞的方式实时有效地进行日志拖尾 python

How to do log tailing in realtime efficiently and in an unblocking manner in tornado python

我在一个基于龙卷风的 python 项目中有一个小网络应用程序,我需要实施实时日志拖尾(我坚持的少数事情之一)。该行为应该类似于 unix 的 tail -f。如果它能在所有平台上工作,那会很好,但对于初学者来说,只需要 unix 就足够了。

我在 Whosebug 和其他地方搜索了很多方法,但没有找到我要找的东西。 Pythonic 解决方案不能很好地跟踪旋转日志或有时无法访问的文件。

因此我选择了 python subprocess 的方式。但是,由于缺少示例,我无法使用龙卷风的 Subprocess class。所以我尝试了使用 run_in_executor 方法的正常子流程。我不确定这是否是一个好方法,或者我是否会有未来的问题。


def tail(self, file):
        self.__process = subprocess.Popen(["tail", "-n", "1", "-f", file], stdout=subprocess.PIPE)

        while 1:
            line = self.__process.stdout.readline()
            print(line)
            # call a sync marked method and push line data
            asyncio.sleep(.0001)
            if not line:
                asyncio.sleep(.5)


    async def start_tail(self):
        # start here
        tornado.ioloop.IOLoop.current().run_in_executor(self.executor, self.tail, self.__log_path)
        pass

这里的问题是我需要将 line 推入队列。该队列位于标记为 async 的函数中。要调用 async 方法,它说调用方法也应该是 async。在那种情况下,我会得到一个错误:coroutines cannot be used with run_in_executor。所以我对如何完成这项工作感到困惑。

我希望日志尾部像标准 linux tail -f 命令一样工作。它不应该阻止我的 Tornado 循环与其他正在进行的事情(例如网络请求、websocket 消息等)。我应该能够将 line 数据发送到我的代码库中的任何同步或异步方法。

使用 tornado.process.Subprocess 而不是 subprocess.Popen(及其 STREAM 选项而不是 PIPE)。这使您可以异步读取子进程:

async def tail(self, file):
    self.__process = Subprocess(["tail", "-n", "1", "-f", file], stdout=Subprocess.STREAM)
    while True:
        line = await self.__process.stdout.read_until(b"\n")
        do_something(line)

def start_tail(self):
    IOLoop.current().spawn_callback(self.tail, self.__log_path)