Python: ожидание достижения размера файла дружественным к процессору способом - PullRequest
2 голосов
/ 15 июля 2011

Я наблюдаю за файлом в Python и запускаю действие, когда оно достигает определенного размера.Сейчас я сплю и опрашиваю, но я уверен, что есть более элегантный способ сделать это:

POLLING_PERIOD = 10
SIZE_LIMIT = 1 * 1024 * 1024
while True:
    sleep(POLLING_PERIOD)
    if stat(file).st_size >= SIZE_LIMIT:
        # do something

Дело в том, что, если у меня большой POLLING_PERIOD, мой предел файла не точен, еслифайл быстро растет, но если у меня небольшой POLLING_PERIOD, я теряю процессор.

Спасибо!

Как я могу это сделать?

Спасибо!

Ответы [ 4 ]

4 голосов
/ 15 июля 2011

Linux Solution

Вы хотите посмотреть, используя pyinotify это привязка Python для inotify .

Вот пример наблюдения за событиями close, это не большой скачок для прослушивания изменений размера.

#!/usr/bin/env python

import os, sys
from pyinotify import WatchManager, Notifier, ProcessEvent, EventsCodes

def Monitor(path):
    class PClose(ProcessEvent):
        def process_IN_CLOSE(self, event):
            f = event.name and os.path.join(event.path, event.name) or event.path
            print 'close event: ' + f

    wm = WatchManager()
    notifier = Notifier(wm, PClose())
    wm.add_watch(path, EventsCodes.IN_CLOSE_WRITE|EventsCodes.IN_CLOSE_NOWRITE)

    try:
        while 1:
            notifier.process_events()
            if notifier.check_events():
                notifier.read_events()
    except KeyboardInterrupt:
        notifier.stop()
        return


if __name__ == '__main__':
    try:
        path = sys.argv[1]
    except IndexError:
        print 'use: %s dir' % sys.argv[0]
    else:
        Monitor(path)

Windows Solution

pywin32 имеет привязки для уведомлений файловой системы для файловой системы Windows.

То, что вы хотите найти, это использовать FindFirstChangeNotification , связать его и перечислить FILE_NOTIFY_CHANGE_SIZE. В этом примере прослушивается изменение имени файла. Это не большой скачок для прослушивания изменений размера.

import os

import win32file
import win32event
import win32con

path_to_watch = os.path.abspath (".")

#
# FindFirstChangeNotification sets up a handle for watching
#  file changes. The first parameter is the path to be
#  watched; the second is a boolean indicating whether the
#  directories underneath the one specified are to be watched;
#  the third is a list of flags as to what kind of changes to
#  watch for. We're just looking at file additions / deletions.
#
change_handle = win32file.FindFirstChangeNotification (
  path_to_watch,
  0,
  win32con.FILE_NOTIFY_CHANGE_FILE_NAME
)

#
# Loop forever, listing any file changes. The WaitFor... will
#  time out every half a second allowing for keyboard interrupts
#  to terminate the loop.
#
try:

  old_path_contents = dict ([(f, None) for f in os.listdir (path_to_watch)])
  while 1:
    result = win32event.WaitForSingleObject (change_handle, 500)

    #
    # If the WaitFor... returned because of a notification (as
    #  opposed to timing out or some error) then look for the
    #  changes in the directory contents.
    #
    if result == win32con.WAIT_OBJECT_0:
      new_path_contents = dict ([(f, None) for f in os.listdir (path_to_watch)])
      added = [f for f in new_path_contents if not f in old_path_contents]
      deleted = [f for f in old_path_contents if not f in new_path_contents]
      if added: print "Added: ", ", ".join (added)
      if deleted: print "Deleted: ", ", ".join (deleted)

      old_path_contents = new_path_contents
      win32file.FindNextChangeNotification (change_handle)

finally:
  win32file.FindCloseChangeNotification (change_handle)

OSX Solution

В файловой системе OSX также есть эквивалентные хуки, использующие PyKQueue, но если вы можете понять эти примеры, вы также можете найти решение для OSX в Google.

Вот хорошая статья о Межплатформенном мониторинге файловой системы .

2 голосов
/ 15 июля 2011

Вы правы: "Опрос - это зло". Чем чаще вы проводите опрос, тем больше вы тратите ресурсы процессора, если ничего не происходит. Если вы проводите опрос реже, вы задерживаете передачу события, когда оно происходит.

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

Если вы работаете в Linux, вы можете использовать «inotify»:

http://linux.die.net/man/7/inotify

1 голос
/ 15 июля 2011

Вы правы, что опрос, как правило, является неоптимальным решением по сравнению с другими способами достижения чего-либо.Однако иногда это самое простое решение, особенно если вы пытаетесь написать что-то, что будет работать как в Windows, так и в Linux / UNIX.

К счастью, современное оборудование работает довольно быстро.На моей машине я смог запустить ваш цикл, опрашивая десять раз в секунду, без какого-либо видимого влияния на использование процессора в диспетчере задач Windows.100 раз в секунду приводили к небольшим препятствиям на графике использования, и загрузка ЦП иногда доходила до 1%.

Десять секунд между опросами, как в вашем примере, совершенно тривиально с точки зрения использования ЦП.

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

0 голосов
/ 15 июля 2011

Немного непонятно, но, учитывая загадку загрузки ЦП в зависимости от размера, будет ли переменный период опроса подходящим?

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

Например, до тех пор, пока текущий размер файла не достигнет определенного порога (или уровней порогов), выя бы допустил более длительный период.
Еще одна эвристика: если размер файла не изменился с прошлого раза, что не указывает на текущую активность файла, вы можете дополнительно увеличить период на доли секунды.(Или сравнение временной метки файла с текущим временем может подойти?).

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

  • Каков абсолютный минимальный промежуток времени, в течение которого файл увеличивается до 10% от ограничения размера?
  • Каков средний объем данных, записанных в эти файлы за 24 часа?
  • Много ли различий в скорости роста файлов в разное время дня и ночи?
  • Какова частота изменения размера файла?
    Является ли это «непрерывным» ведением журнала, при котором в среднем происходит несколько десятков операций записи в секунду или записи выполняются реже, но при этом помещается гораздо больше данныхсразу, когда они делают?
  • и т. Д.

В качестве альтернативы, но с риском внедрения в вашу программу логики, специфичной для ОС , вы можете посмотреть изменения файла / каталогасистемы оповещения .Я знаю, что и WIN32 API, и Linux предлагают свою разновидность этой функции.Мне неизвестно о конкретной реализации, которую используют ОС, и они вполне могут представить какой-то подход к опросу, подобный тому, который у вас есть снаружи.Тем не менее, ОС имеет различные хуки в файловой системе, что может сделать ее реализацию менее навязчивой.

...