Как реализовать pythonic эквивалент хвоста-F?

Обычно я предпочитаю первого, как особенно, когда строки становятся длинными, может быть намного легче читать.

другое преимущество, я верю одной из производительности, поскольку последний на самом деле выполняет 2 строковых оператора создания прежде, чем передать заключительную строку Консоли. Метод записи. Строка. Формат использует StringBuilder под покрытиями, которым я верю, таким образом, нескольких конкатенаций избегают.

нужно отметить однако это, если параметры Вы являетесь передающими в Представить в виде строки. Формат (и другие такие методы как Консоль. Запишите), типы значения тогда, они будут упакованы, прежде чем передано в, который может обеспечить его собственные хиты производительности. Сообщение в блоге на этом здесь .

25
задан dbr 9 November 2009 в 21:37
поделиться

7 ответов

Ну, самый простой способ - постоянно читать из файла, проверять, что нового, и проверять совпадения.

import time

def watch(fn, words):
    fp = open(fn, 'r')
    while True:
        new = fp.readline()
        # Once all lines are read this just returns ''
        # until the file changes and a new line appears

        if new:
            for word in words:
                if word in new:
                    yield (word, new)
        else:
            time.sleep(0.5)

fn = 'test.py'
words = ['word']
for hit_word, hit_sentence in watch(fn, words):
    print "Found %r in line: %r" % (hit_word, hit_sentence)

Это решение с readline работает, если вы знаете, что ваши данные будут отображаться в строках.

Если данные представляют собой какой-то поток, вам нужен буфер, больший, чем самое большое слово , которое вы ищете, и сначала заполните его. Так все становится немного сложнее ...

24
ответ дан 28 November 2019 в 21:13
поделиться

Вы можете использовать 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)
4
ответ дан 28 November 2019 в 21:13
поделиться
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".

5
ответ дан 28 November 2019 в 21:13
поделиться

РЕДАКТИРОВАТЬ: как указано в комментарии ниже, O_NONBLOCK не работает для файлов на диске. Это по-прежнему поможет, если кто-то еще придет и захочет отслеживать данные, поступающие из сокета, именованного канала или другого процесса, но он не отвечает на фактический вопрос, который был задан . Оригинальный ответ останется ниже для потомков. (Обращение к tail и grep будет работать, но в любом случае это не ответ.)

Либо откройте файл с помощью O_NONBLOCK и используйте select для опроса на предмет доступности для чтения а затем прочтите , чтобы прочитать новые данные, и строковые методы для фильтрации строк в конце файла ... или просто используйте модуль подпроцесса и позвольте хвосту и grep выполняют всю работу за вас так же, как и в оболочке.

3
ответ дан 28 November 2019 в 21:13
поделиться

Если вы не можете ограничить проблему, чтобы она работала для чтения на основе строки, вам нужно прибегнуть к блокам.

Это должно работать:

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

Проблема заключается в том, чтобы гарантировать, что вы совпадаете с иглой, даже если она разделена двумя границами блока.

1
ответ дан 28 November 2019 в 21:13
поделиться

Насколько мне известно, в списке функций Python нет эквивалента «хвосту». Решением было бы использовать tell () (получить размер файла) и read () для определения конечных строк.

В этом сообщении в блоге (не мной) есть функция, выписанная, мне кажется подходящей! http://www.manugarg.com/2007/04/real-tailing-in-python.html

0
ответ дан 28 November 2019 в 21:13
поделиться

Вы можете использовать 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.

-1
ответ дан 28 November 2019 в 21:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: