28

特定のキーワードの出現について、成長しているファイルの末尾を監視するpythonicの方法は何ですか?

シェルでは、次のように言うかもしれません:

tail -f "$file" | grep "$string" | while read hit; do
    #stuff
done
4

10 に答える 10

6
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」マッチの代わりに正規表現がサポートされています。

于 2009-11-09T21:33:05.040 に答える
4

編集:以下のコメントにあるように、O_NONBLOCKディスク上のファイルでは機能しません。これは、他の誰かがソケットや名前付きパイプ、または別のプロセスからのデータを尾行することを検討している場合でも役立ちますが、実際に尋ねられた質問には答えません。後世のために元の答えは以下に残ります。(tailとgrepを呼び出すことは機能しますが、とにかく一種の答えではありません。)

でファイルを開き、O_NONBLOCKを使用selectして読み取りの可用性をポーリングしてreadから、新しいデータと文字列メソッドを読み取ってファイルの最後の行をフィルタリングするか、subprocessモジュールを使用して、次のようtailgrep作業を行います。あなたはシェルにいるでしょう。

于 2009-11-09T20:55:27.107 に答える
4

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)
于 2009-11-09T21:33:53.597 に答える
3

pytailfを使用できます:単純な python tail -f wrapper

from tailf import tailf    

for line in tailf("myfile.log"):
    print line
于 2015-03-16T11:02:49.707 に答える
2

そのためのパッケージがあるようです: https://github.com/kasun/python-tail

于 2013-09-11T17:38:24.113 に答える
1

行ベースの読み取りで機能するように問題を制約できない場合は、ブロックに頼る必要があります。

これは機能するはずです:

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つのブロック境界で区切られている場合でも、針を確実に一致させることにあります。

于 2009-11-09T20:54:08.373 に答える
-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 を実装するための端正で簡潔な方法です。

于 2009-11-09T21:17:33.210 に答える