utamaro’s blog

誰かの役に立つ情報を発信するブログ

watchdogを使ってファイルを監視する

カレントディレクトリの*.logに変更があった場合にMyHandler内のメソッドが実行される。

最初は.logファイルで修正したらon_modifiedが呼ばれると考えていたが、実際はon_deletedon_createdの順番で呼ばれていた。

class MyHandler(PatternMatchingEventHandler):
    def __init__(self, command, patterns):
        super(MyHandler, self).__init__(patterns=patterns)
        self.command = command

    def _run_command(self):
        subprocess.call([self.command, ])

    def on_moved(self, event):
        print("called on_moved")

    def on_created(self, event):
        print("called on_created")

    def on_deleted(self, event):
        print("called on_deleted")

    def on_modified(self, event):
        print("called on_modified")

def watch(path, command, extensions):
    event_handler = MyHandler(command, extensions)
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()


if __name__ == '__main__':
    watch("./", "ls", ["*.log"])

念のため、別のイベントハンドラを使って試してみた。

同様に.logファイルを更新した場合の動作。

この場合だと、以下の順番で実行される

  1. file './secure_test.log' deleted.
  2. file './secure_test.log' created.
  3. directory './' modified.
  4. directory './.idea' modified.
class EventHandler(FileSystemEventHandler):
    def on_created(self, event):
        if event.is_directory:
            print('directory \'{0}\' created.'.format(event.src_path))
        else:
            print('file \'{0}\' created.'.format(event.src_path))

    def on_modified(self, event):
        if event.is_directory:
            print('directory \'{0}\' modified.'.format(event.src_path))
        else:
            print('file \'{0}\' modified.'.format(event.src_path))

    def on_deleted(self, event):
        if event.is_directory:
            print('directory \'{0}\' deleted.'.format(event.src_path))
        else:
            print('file \'{0}\' deleted.'.format(event.src_path))

def watch():
    event_handler = EventHandler()
    observer = Observer()
    observer.schedule(event_handler, "./")
    observer.start()

    try:
        while True:
            time.sleep(10)
    except (Exception, KeyboardInterrupt):
        observer.stop()
    observer.join()


if __name__ == '__main__':
    watch()

まとめ

どうやら、modifiedが実行されるのはディレクトリに変更があった場合に限るらしい

最初のプログラムではカレントディレクトリ以下の.logファイルのみを見ているため、modifiedが実行されなかったと思われる。

ファイルの変更をキャッチする場合は、deletecreateの順番で実行されたことが確認されたら処理するようにするのが良い。

ファイルの生成時はcreateが実行される

ファイルの削除時はdeleteが実行される

ファイルの編集時はdeletecreateが実行される

ファイル名を変更した場合はmoveが実行される