Обычно я предпочитаю первого, как особенно, когда строки становятся длинными, может быть намного легче читать.
другое преимущество, я верю одной из производительности, поскольку последний на самом деле выполняет 2 строковых оператора создания прежде, чем передать заключительную строку Консоли. Метод записи. Строка. Формат использует StringBuilder под покрытиями, которым я верю, таким образом, нескольких конкатенаций избегают.
нужно отметить однако это, если параметры Вы являетесь передающими в Представить в виде строки. Формат (и другие такие методы как Консоль. Запишите), типы значения тогда, они будут упакованы, прежде чем передано в, который может обеспечить его собственные хиты производительности. Сообщение в блоге на этом здесь .
Ну, самый простой способ - постоянно читать из файла, проверять, что нового, и проверять совпадения.
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
работает, если вы знаете, что ваши данные будут отображаться в строках.
Если данные представляют собой какой-то поток, вам нужен буфер, больший, чем самое большое слово
, которое вы ищете, и сначала заполните его. Так все становится немного сложнее ...
Вы можете использовать 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)
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
для опроса на предмет доступности для чтения а затем прочтите
, чтобы прочитать новые данные, и строковые методы для фильтрации строк в конце файла ... или просто используйте модуль подпроцесса и позвольте
хвосту
и grep
выполняют всю работу за вас так же, как и в оболочке.
Если вы не можете ограничить проблему, чтобы она работала для чтения на основе строки, вам нужно прибегнуть к блокам.
Это должно работать:
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
Проблема заключается в том, чтобы гарантировать, что вы совпадаете с иглой, даже если она разделена двумя границами блока.
Насколько мне известно, в списке функций Python нет эквивалента «хвосту». Решением было бы использовать tell () (получить размер файла) и read () для определения конечных строк.
В этом сообщении в блоге (не мной) есть функция, выписанная, мне кажется подходящей! http://www.manugarg.com/2007/04/real-tailing-in-python.html
Вы можете использовать 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.