特定のキーワードの出現について、成長しているファイルの末尾を監視するpythonicの方法は何ですか?
シェルでは、次のように言うかもしれません:
tail -f "$file" | grep "$string" | while read hit; do
#stuff
done
def tail(f):
f.seek(0, 2)
while True:
line = f.readline()
if not line:
time.sleep(0.1)
continue
yield line
def process_matches(matchtext):
while True:
line = (yield)
if matchtext in line:
do_something_useful() # email alert, etc.
list_of_matches = ['ERROR', 'CRITICAL']
matches = [process_matches(string_match) for string_match in list_of_matches]
for m in matches: # prime matches
m.next()
while True:
auditlog = tail( open(log_file_to_monitor) )
for line in auditlog:
for m in matches:
m.send(line)
これを使用して、ログ ファイルを監視します。完全な実装では、list_of_matches を構成ファイルに保持して、複数の目的に使用できるようにします。私の拡張機能のリストには、単純な「in」マッチの代わりに正規表現がサポートされています。
編集:以下のコメントにあるように、O_NONBLOCK
ディスク上のファイルでは機能しません。これは、他の誰かがソケットや名前付きパイプ、または別のプロセスからのデータを尾行することを検討している場合でも役立ちますが、実際に尋ねられた質問には答えません。後世のために元の答えは以下に残ります。(tailとgrepを呼び出すことは機能しますが、とにかく一種の答えではありません。)
でファイルを開き、O_NONBLOCK
を使用select
して読み取りの可用性をポーリングしてread
から、新しいデータと文字列メソッドを読み取ってファイルの最後の行をフィルタリングするか、subprocess
モジュールを使用して、次のようtail
にgrep
作業を行います。あなたはシェルにいるでしょう。
select を使用して、ファイル内の新しいコンテンツをポーリングできます。
def tail(filename, bufsize = 1024):
fds = [ os.open(filename, os.O_RDONLY) ]
while True:
reads, _, _ = select.select(fds, [], [])
if 0 < len(reads):
yield os.read(reads[0], bufsize)
pytailfを使用できます:単純な python tail -f wrapper
from tailf import tailf
for line in tailf("myfile.log"):
print line
そのためのパッケージがあるようです: https://github.com/kasun/python-tail
行ベースの読み取りで機能するように問題を制約できない場合は、ブロックに頼る必要があります。
これは機能するはずです:
import sys
needle = "needle"
blocks = []
inf = sys.stdin
if len(sys.argv) == 2:
inf = open(sys.argv[1])
while True:
block = inf.read()
blocks.append(block)
if len(blocks) >= 2:
data = "".join((blocks[-2], blocks[-1]))
else:
data = blocks[-1]
# attention, this needs to be changed if you are interested
# in *all* matches separately, not if there was any match ata all
if needle in data:
print "found"
blocks = []
blocks[:-2] = []
if block == "":
break
課題は、2つのブロック境界で区切られている場合でも、針を確実に一致させることにあります。
collections.deque
テールを実装するために使用できます。
http://docs.python.org/library/collections.html#deque-recipesから...
def tail(filename, n=10):
'Return the last n lines of a file'
return deque(open(filename), n)
もちろん、これはファイルの内容全体を読み取りますが、tail を実装するための端正で簡潔な方法です。