python - 如何在龙卷风python中以无阻塞的方式有效地实时进行日志拖尾
问题描述
我在基于龙卷风的 python 项目中有一个小 webapp,我需要实现实时日志拖尾(我坚持的少数事情之一)。行为应该类似于 unix 的tail -f
. 如果它适用于所有平台,那就太好了,但对于初学者来说,unix 就足够了。
我在stackoverflow和其他地方搜索了很多方法,但没有找到我要找的东西。Pythonic 解决方案在跟踪轮换日志或文件有时无法访问方面并不好。
因此,我采用了 pythonsubprocess
方式。Subprocess
但是由于缺少示例,我无法使用龙卷风的课程。所以我尝试了正常的子流程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
。所以我对如何完成这项工作感到困惑。
我希望日志拖尾能够像使用标准 linuxtail -f
命令一样工作。它不应该阻止我的 Tornado 循环与其他正在发生的事情(例如 web 请求、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)
推荐阅读
- reactjs - 我如何只希望单击的项目出现在模式上?
- python - Python 对 CSV 的请求
- java - Spring Boot 可运行 jar 中的 ANT 类路径
- vue.js - VueJS - 如何在同一个组件中使用道具来指定另一个组件中的值
- html - 如何删除输入类型文件的默认占位符并获取占位符,如下所示?
- angular - 无法连接到 test.mosquitto.org 进行测试
- c# - C#字符串中的引号和斜线标记
- raspberry-pi - 在树莓派上开始使用 reportlab
- xaml - 应用固定/静态 Listview 高度后,Listview 项目不滚动
- apache-kafka - kafka 消息键作为 HDFS 中的关键字段/列