如何读取重定向/管道数据?

2024-04-28 19:32:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我的日志文件位于:

/mfs/log/scribe/clicklog/*/clicklog_current

我想用Python实时处理它,所以我创建了一个transform.py文件:

tail -f /mfs/log/scribe/clicklog/*/clicklog_current | grep 'pattern' | ./transform.py

tranform.py中:

def process_line(line):
    print real_process(line)

问题是:每次有新行来自stdin时,如何调用process_line?你知道吗


Tags: 文件pylogdeflinetransformcurrentprocess
3条回答

通过使用^{}grep模块,您可以完全摆脱tail -f部分(尽管在本例中,您甚至不需要它,因为您的搜索条件可以编写为简单的成员资格测试)。你知道吗

下面是一个简单的示例(根据文档进行了修改),可以满足您的要求:

import sys
import time
from watchdog.observers import Observer
from watchdog.handlers import FileSystemEventHandler

class WatchFiles(FileSystemEventHandler):

    def process_file(self, event):
        """
        does stuff the file
        """
        with open(event.src_path, 'r') as f:
            for line in f:
                if 'pattern' in line:
                   do_stuff(line)

    def on_modified(self, event):
        self.process_file(event)

    def on_created(self, event):
        self.process_file(event)

if __name__ == "__main__":
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    observer = Observer()
    observer.schedule(WatchFiles(), path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

这样,您的应用程序不仅更易于移植,而且其所有部分都是独立的。你知道吗

无论何时发生重定向或管道,标准输入流都将设置为该值。所以你可以直接从^{}读取,就像这样

import sys

for line in sys.stdin:
    process_line(line)

如果缓冲占用了您的时间,您可以调整/禁用输入缓冲,如this answer中所述

减小缓冲区大小:

import os
import sys

for line in os.fdopen(sys.stdin.fileno(), 'r', 100):
    process_line(line)

现在它最多只能缓冲100个字节

禁用缓冲:

引用官方文件

^{}

Force stdin, stdout and stderr to be totally unbuffered. On systems where it matters, also put stdin, stdout and stderr in binary mode.

Note that there is internal buffering in file.readlines() and File Objects (for line in sys.stdin) which is not influenced by this option. To work around this, you will want to use file.readline() inside a while 1: loop.

^{}库可能可以执行您要查找的操作。你知道吗

import fileinput
for line in fileinput.input():
    if line == '': pass
    process_line(line)

相关问题 更多 >