Befehlsausführung ausgelöst durch Dateiaktualisierung (Python Edition)

Es ist eine Weile her, aber ich habe einen Artikel wie diesen über Qiita gefunden. Oder besser gesagt, es kam von @wpythonnews.

Führen Sie den Komponententest aus, sobald Sie die Datei speichern

Die hier vorgestellte Methode besteht darin, den Zeitstempel der letzten Aktualisierung zu speichern und die Aktualisierungszeit der Dateien im Zielverzeichnis nacheinander zu überprüfen.

Die Prüfung selbst wird alle 100 ms ausgeführt, und obwohl die CPU nicht mit voller Kapazität ausgeführt wird, hat sie dennoch eine bestimmte Last. Über 77% Last auf meinem Mac. Außerdem fühle ich mich durch diesen Code unlesbar, wenn mehrere Dateien in 100 ms aktualisiert werden (die Ergebnisse variieren je nach der Reihenfolge, in der sie ausgewertet werden).

Andererseits ist es sicher, dass es einige Situationen gibt, in denen diese Art der "Bestätigung der Dateiaktualisierung" erforderlich ist. Daher werden neuere Betriebssysteme auf Kernelebene unterstützt.

Vielleicht gibt es Python-Module, die diese verwenden. Wenn ich es nachschaue, kommt es auf verschiedene Arten heraus.

Epoll und kqueue werden übrigens vom Standard-Python-Modul (select) mit einer niedrigeren I / F-Ebene als andere unterstützt. Es gibt.

Unter den oben genannten Modulen scheint Watchdog das beste zu sein, wenn Sie ein Allzweckprogramm schreiben, indem Sie für jede Plattform unterschiedliche APIs verwenden. Also habe ich versucht, es zu benutzen.

Verwenden Sie zur Installation das übliche Rohr.

shell::


$ pip install watchdog

Und der Beispielcode sieht so aus.

python::dirwatch2.py


#!/usr/bin/env python
from __future__ import print_function

import sys
import time
import subprocess
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler


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):
        self._run_command()

    def on_created(self, event):
        self._run_command()

    def on_deleted(self, event):
        self._run_command()

    def on_modified(self, event):
        self._run_command()


def watch(path, command, extension):
    event_handler = MyHandler(command, ["*"+extension])
    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__":
    if 4 > len(sys.argv):
        print("Usage:", sys.argv[0], "dir_to_watch command extension")
    else:
        watch(sys.argv[1], sys.argv[2], sys.argv[3])

Es ist etwas länger, aber die Grundlagen sind einfach. Erstellen Sie einfach eine Klasse, die eine der vorbereiteten Ereignishandlerklassen erbt, und implementieren Sie den Inhalt von on_moved, on_created, on_deleted, on_modified. Diese Methoden werden beim Verschieben, Erstellen, Löschen oder Ändern von Dateien aufgerufen.

Übrigens werden die folgenden vier Event-Handler-Klassen vorbereitet.

Die erste ist eine Basisklasse, die die Verarbeitung von Dateiänderungsereignissen behandelt, und die zweite und dritte Klasse fügen eine Funktion hinzu, mit der Dateien durch Mustervergleich oder reguläre Ausdrücke eingegrenzt werden können. Der vierte ist ein Handler, der Dateiänderungsereignisse als Protokoll schreibt.

Da PatternMatchingEventHandler hier durch Erweiterung eingegrenzt werden soll, wird PatternMatchingEventHandler vererbt und implementiert, sodass der Befehl unabhängig davon ausgegeben wird, welche der vier Handlermethoden aufgerufen wird.

Erstellen Sie dann einfach eine Instanz der Observer-Klasse, übergeben Sie den Ereignishandler und das zu überwachende Verzeichnis an Schedule () und start (). Danach gibt es einen Prozess, der jede Sekunde in einer Endlosschleife abläuft. Dies dient jedoch dazu, das Schlüsselereignis zu erfassen, damit die Ausführung mit Strg-C gestoppt werden kann. Dies verbraucht ein wenig CPU, aber es sind ungefähr 10% zur Hand. Nun, ist es akzeptabel? Sie kann durch Erhöhen des Intervalls weiter reduziert werden.

Obwohl das Beispiel ausgeführt wird, wird das Argument des Befehls mit der Dirwatch von "Unit-Test zum Zeitpunkt des Speicherns der Datei ausführen abgeglichen. Die Ausführung ist wie folgt.

shell::


$ python dirwatch2.py <directory_to_watch> <command> <extension>

Eine Datei mit der angegebenen Erweiterung unter dem angegebenen Verzeichnis Der angegebene Befehl wird ausgegeben, wenn die Datei geändert wird.

Beachten Sie, dass dieses Python-Modul namens watchdog mit dem Tool "watchmedo" geliefert wird, um dasselbe zu tun. Damit können Sie wie folgt schreiben:

shell::


$ watchmedo shell-command \
	--patterns="*"$3 \
	--command $2 \
	--recursive \
	$1

Es war leicht zu schlagen.

Ebenso kann "Überwachen von Dateien und Verzeichnissen und Ausführen von Änderungen" ganz normal mit Node.js Tools wie Grunt und Gulp durchgeführt werden. Ich möchte sie auch zusammenfassen.

Recommended Posts

Befehlsausführung ausgelöst durch Dateiaktualisierung (Python Edition)
Externe Befehlsausführung in Python
Ausführung durch Subshell (und Variablenaktualisierung)
Lesen Sie die Datei Zeile für Zeile mit Python
Python-Update (2.6-> 2.7)
Lesen Sie die Datei Zeile für Zeile mit Python
Fehler und Abschluss der Ausführung durch LINE [Python] benachrichtigen
Lesen Sie mit Python Zeile für Zeile aus der Datei
Rufen Sie das Aktualisierungsdatum der Python-Memorandum-Datei ab.
Skript-Python-Datei
Python-Dateiverarbeitung
Lesen Sie die XML-Datei anhand des Python-Tutorials
Sprachdateierkennung durch Google Speech API v2 mit Python