Problem mit QtFileWatcher

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
ws
User
Beiträge: 65
Registriert: Freitag 16. Juni 2006, 13:19

Hallo,

für eine Applikation brauche ich eine Dateisystemüberwachung, d.h. ich muss feststellen, wenn bestimmte Dateien in einem Kommunikationsverzeichnis geändert werden, um darauf reagieren zu können.
Da die Applikation PyQt benutzt, habe ich entsprechend versucht, dafür den QtFileWatcher zu verwenden. Mein Code sieht so aus (gekürzt):

Code: Alles auswählen

class Ui_WSMMain(QtGui.QMainWindow):
    
    def show(self):
        ...

    def __init__(self, parent=None):
                
        QtGui.QMainWindow.__init__(self, parent)
        
        
        # create a file system monitor to watch the communication dir

        self._fsMonitor = QtCore.QFileSystemWatcher(self)
        self._fsMonitor.addPath(WsManager().commDir)
        self._fsMonitor.addPath(WsManager().commFile)
        
        self.connect(self._fsMonitor, QtCore.SIGNAL("directoryChanged(const QString&)"), self._commDirEventHandler)
        self.connect(self._fsMonitor, QtCore.SIGNAL("fileChanged(const QString&)"), self._commFileEventHandler)


    def _commFileEventHandler(self, theString):
        """
        Handles file events for the communication file.
        """
        sys.stderr.write("*** fileEvent:%s\n" % theString)
        sys.stderr.flush()

    def _commDirEventHandler(self, theString):
        """
        Handles file events for the communication file.
        """
        sys.stderr.write("*** dirEvent:%s\n" % theString)
        sys.stderr.flush()

Mein Problem ist nun, dass das Event für directoryChanged immer zuverlässig detektiert wird, für fileChanged dagegen nur beim ersten Mal.

Kennt jemand das Problem und weiss einen Workaround (ausser bei jedem directoryChanged-Event alle Dateien auf Veränderungen untersuchen)? Mit Googeln habe ich nichts gefunden.

Ich benutze Qt 4.3.2 unter Windows XP.

Vielen Dank im Voraus

Wolfgang
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Wenn das alles nicht klappt machs doch selbst.

Ein dict mit filename und 'most recent change' und eben alle paar sekunden die files prüfen. Was anderes wird der Filewatcher wohl auch nicht machen.


als tip:

Code: Alles auswählen

import os
st_mtime = os.stat(r'C:\autoexec.bat')[8]
EDIT:
Ein os.stat call ist äußerst Ressourcensparend.
Das ganze in eine Klasse mit eigenem Thread gepackt,
dazu bei Anderung ein .PostEvent(MyFileHasChangedEvent) sollte praktisch das ganze ersetzen.

(Zumindest ist es bei wxWidgets PostEvent, bei Qt kenn ich mich nicht aus ;-)

Und diese Klasse mit geschätzt 60 Zeilen kannst du auch überall ohne Qt dann benutzen mit nur kleinen änderungen. ;)
Zuletzt geändert von Mad-Marty am Dienstag 20. November 2007, 22:38, insgesamt 2-mal geändert.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Leider schreiben sie nicht, wie QtFileSystemWatcher funktioniert. Unter Linux gab es mal FAM, der Änderungen über Polling überwacht hat, welches inzwischen durch das wesentlich elegantere GAMIN ersetzt wurde, welches `inotify` benutzt. Mit `pyinotify` kann man es auch in Python nutzen.

Ob es unter Windows eine `inotify`-Ähnliche Funktionalität gibt weiß ich nicht - da müsstest du mal schauen, aber ich denke schon dass da irgednwas sein muss.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Leonidas hat geschrieben:Ob es unter Windows eine `inotify`-Ähnliche Funktionalität gibt weiß ich nicht - da müsstest du mal schauen, aber ich denke schon dass da irgednwas sein muss.
Zumindest in .NET ist so etwas vorhanden. ;)
http://msdn2.microsoft.com/de-de/librar ... S.80).aspx
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
ws
User
Beiträge: 65
Registriert: Freitag 16. Juni 2006, 13:19

Danke für alle Antworten.

ch habe mich noch etwas weiter mit dem Problem beschäftigt und dabei festgestellt, warum das "Watchen" nicht so richtig funktioniert. Das Problem scheint zu sein, dass ich jeweils versucht habe, mit gvim die betreffende Datei zu ändern. Wenn man aber mit vim speichert, passieren (auf einem heutigen Rechner sehr schnell hintereinander) mehrere File-/Directory-Events, zumindest wird das .swp-File und das zu speichernde File geschrieben. Diese Events treten anscheinend so dicht hintereinander auf, dass einzelne Events "verschluckt" werden (das steht auch so in der Qt-Doku). Das passiert nicht, wenn man von der Shell aus etwa

echo "..." >> fileToWatch.txt

aufruft, in diesem Fall arbeitet der FileWatcher wie erwartet.

Bei modernen Applikationen ist davon auszugehen, dass sie sehr viel Dateisystem-Traffic bei einem einfachen Speichern auslösen (angeblich etwa bei Word bis zu 40 Changes bei einfachem Speichern!)
BlackJack

Damit ist dieser FileWatcher doch relativ sinnlos wenn Änderungsnachrichten auch verschluckt werden können!?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Komisch, ich finde weder in der Dokumentation zu Qt 3.3 noch 4.3 irgendwas zu diesem FileWatcher.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ws
User
Beiträge: 65
Registriert: Freitag 16. Juni 2006, 13:19

Hallo Leonidas,

im Beispielcode war's richtig, im Subject falsch ...

http://doc.trolltech.com/qtopia4.2/qfil ... tcher.html

Gruss

Wolfgang
ws
User
Beiträge: 65
Registriert: Freitag 16. Juni 2006, 13:19

Hallo Blackjack,

leider scheinen viele Verfahren, die File System Watching über Callbacks implementieren, unzuverlässig zu sein.

Ich hatte vor QFileSystemWatcher schon mit der gewrappten ReadDirectoryChangesW-Api (schöne Seite zum Thema: http://tgolden.sc.sabren.com/python/win ... anges.html)
herumexperimentiert und festgestellt (mit nosetests), dass mindestens ein Event aus einer Reihe von 5 minimalen Dateioperationen fast immer verlorenging. Ich konnte das Verhalten nur dadurch verbessern, dass ich zwischen die Tests kleine sleeps() eingebaut habe.

Gruss

Wolfgang
lunar

Leonidas hat geschrieben:Leider schreiben sie nicht, wie QtFileSystemWatcher funktioniert.
Unter Linux benutzt er afaik inotify.
Unter Linux gab es mal FAM, der Änderungen über Polling überwacht hat,
Sicher? Ich war mir bisher immer sicher, dass FAM optional auch inotify oder zumindest dessen Vorgänger dnotify unterstützen würde...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

lunar hat geschrieben:Sicher? Ich war mir bisher immer sicher, dass FAM optional auch inotify oder zumindest dessen Vorgänger dnotify unterstützen würde...
Habe jetzt nachgeschaut. FAM kann einen "kernel monitor" verwenden - Standardmäßig IMon, DNotify per Patch. Von inotify habe ich offiziell nichts gesehen, kann aber sein, dass Distributoren auch das reingepatcht haben. Gamin unterstützt inzwischen aber offiziell inotify.

Wobei es zu prüfen wäre, ob inotify genauso unzuverlässig ist, wie die Win32-API.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

Leonidas hat geschrieben:
lunar hat geschrieben:Sicher? Ich war mir bisher immer sicher, dass FAM optional auch inotify oder zumindest dessen Vorgänger dnotify unterstützen würde...
Wobei es zu prüfen wäre, ob inotify genauso unzuverlässig ist, wie die Win32-API.
Und gibt es irgendwelche Anhaltspunkte dafür, dass das der Fall ist? Meines Wissens nicht...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

lunar hat geschrieben:Und gibt es irgendwelche Anhaltspunkte dafür, dass das der Fall ist? Meines Wissens nicht...
Wir haben aber auch keinen Gegenbeweis ;) Ich habe momentan aber leider keine Zeit das zu prüfen. Würde aber auch davon ausgehen, dass `inotify` korrekt funktioniert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

Leonidas hat geschrieben:
lunar hat geschrieben:Und gibt es irgendwelche Anhaltspunkte dafür, dass das der Fall ist? Meines Wissens nicht...
Wir haben aber auch keinen Gegenbeweis ;) Ich habe momentan aber leider keine Zeit das zu prüfen. Würde aber auch davon ausgehen, dass `inotify` korrekt funktioniert.
Ich auch, sonst hätte man nämlich längst Gegenteiliges gehört, und wahrscheinlich auch schon entsprechende Patches auf der LKML gesehen ;) So oft, wie inotify heute eingesetzt wird, können derartig gravierende Fehler nämlich eigentlich nicht unbemerkt bleiben.
Antworten