我的日志文件位于:
/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)
问题是:每当process_line
有新行时,如何拨打stdin
?
答案 0 :(得分:2)
每当重定向或管道发生时,标准输入流将设置为该值。所以你可以直接阅读sys.stdin
,就像这样
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个字节
禁用缓冲:
引用官方文档,
<强> -u
强>
强制stdin,stdout和stderr完全无缓冲。在重要的系统上,还将stdin,stdout和stderr置于二进制模式。
请注意,
file.readlines()
和文件对象(for line in sys.stdin
)中存在内部缓冲,不受此选项的影响。要解决此问题,您需要在file.readline()
内使用while 1: loop
。
答案 1 :(得分:1)
fileinput
库可能能够满足您的需求。
import fileinput
for line in fileinput.input():
if line == '': pass
process_line(line)
答案 2 :(得分:0)
使用tail -f
模块使用watchdog
和grep
可以完全摆脱re
部分(尽管在这种情况下,您甚至不需要因为您的搜索条件可以写成简单的成员资格测试。)
这是一个简单的例子(从文档中修改),可以满足您的需求:
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()
这样,您的应用程序不仅更具可移植性,而且它的所有部分都是自包含的。