Seite 1 von 2
Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Donnerstag 28. Oktober 2021, 10:27
von pyhill00
Watchdog wird verwendet, um neue .hdf5-Dateien zur Verwendung an ein anderes Programm. Das Problem ist, dass mit Queue nur eine Datei gesendet werden kann und Watchdog keine weiteren Dateien sendet, selbst wenn dem Ordner neue Dateien hinzugefügt werden. Ich glaube, das hat damit zu tun, dass Queue block=True verwendet wird und das ist problematisch für Qt, aber ich bin nicht sicher, wie ich das Problem lösen kann. Ich habe versucht, anstelle von Queue eine normale Liste zu verwenden, aber da am Anfang nichts in der Liste ist, erhalte ich einen Fehler, da das Programm bereits ein Element in der Liste finden will (Beispiel für diesen Code ist unten auskommentiert, um zu verstehen, was ich meine).
Im Wesentlichen: der Code funktioniert, wenn eine .hdf5-Datei zum Ordner hinzugefügt wird, aber wenn andere Dateien hinzugefügt werden, werden sie vom Code nicht erkannt.
Hier ist der Code, der den Watchdog-Code auslöst (dieser befindet sich in einer anderen .py-Datei):
Code: Alles auswählen
try:
print('try to connect to event service ...')
self.listener = watchdog_search.get_qt_listener()
self.listener.listener.finishedRun.connect(self.on_finished_run)
except Exception as e:
print(e)
Und hier ist der `watchdog_search` Code:
Code: Alles auswählen
import time
import traceback
import os
import h5py
import queue
from typing import Union
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler, DirCreatedEvent, FileCreatedEvent
from .tools.qt import QtCore
class NewFileHandler(FileSystemEventHandler):
"""h5 file creation handler for Watchdog"""
def __init__(self):
super().__init__()
self.file_queue = queue.Queue()
#self.la = [] #here is the list code I was referring to. I wanted to try to avoid using Queue but the attempt didnt work since an empty list at the beginning gives an error
# callback for File/Directory created event, called by Observer.
def on_created(self, event: Union[DirCreatedEvent, FileCreatedEvent]):
if event.src_path[-4:] == "hdf5":
# run callback with path string
self.file_queue.put(event.src_path)
#self.la.append(event.src_path)
class ObserverWrapper(QtCore.QObject): # New LabBusSubscriber
"""Encapsulated Observer boilerplate"""
if hasattr(QtCore, "QString"):
finishedRun = QtCore.Signal(QtCore.QString, QtCore.QString)
else:
finishedRun = QtCore.Signal(str, str)
can_listen = True
def __init__(self, path: str):#, recursive=True):
super().__init__()
self.path = path
self.observer = Observer()
self.handler = NewFileHandler()
self.observer.schedule(self.handler, path=path, recursive=True)
self.start()
def start(self):
"""
Starts observing for filesystem events. Runs self.routine() every 1 second.
:param blocking: If true, blocks main thread until keyboard interrupt.
"""
self.observer.start()
def stop(self):
"""
Stops the observer. When running self.start(blocking=True) then you don't need to call this.
"""
self.observer.stop()
self.observer.join()
def event(self, event):
"""Here we define what to do at which signal.
In general we will transmit a QT signal to which the other components connect.
"""
print("EVENT", event)
if isinstance(event, QtCore.QEvent):
# make sure the QObject code reacts on QEvents
return QtCore.QObject.event(self, event)
self.finishedRun.emit(event[0], event[1])
def wait_for_file(self):
"""
Wait and Process newly created files
"""
max_retry_count = 3500 # for test purposes now but want to set an upper bound on verifying a file is finished.
# will try h5 file for a max of 35 seconds (upper bound) to see if the file is finished.
# Files are usually finished within 20-30 seconds
#
retry_interval_seconds = .01 # every hundreth it will try the file to see if it finished writing
#file_path = self.handler.la[-1] #this expects already at the beginning an entry but there is no file until one is populated into the folder
file_path = self.handler.file_queue.get(block=True)
file_name = os.path.basename(file_path)
# try to open the file
retry_count = 0
while True:
try:
file = h5py.File(file_path, "r")
file.close()
self.event([file_path, file_name])
break
except OSError:
if retry_count < max_retry_count:
retry_count += 1
print(f"h5 file <{file_path}> is locked, retrying {retry_count}/{max_retry_count}")
time.sleep(retry_interval_seconds)
else:
print(f"h5 file <{file_path}> reached max retry count, skipping")
except Exception as err:
print(f"Got unexpected Error <{type(err).__name__}> while opening <{file_path}> ")
traceback.print_exc()
class QtEventSubscriber(QtCore.QThread):
"""The listener thread"""
def __init__(self):
QtCore.QThread.__init__(self)
self.listener = ObserverWrapper("/home/xxx/Desktop/xxx/MPQ/test_image_analyzer_files/Test_Data/")
self.listener.moveToThread(self)
def run(self):
if self.listener.can_listen:
print("start listener thread")
self.listener.wait_for_file()
else:
print("can't listen: no listener thread")
pass
_qtlistener = None
def get_qt_listener():
global _qtlistener
if _qtlistener is not None:
return _qtlistener
_qtlistener = QtEventSubscriber()
_qtlistener.start()
print(_qtlistener.listener.thread(), _qtlistener)
return _qtlistener
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Donnerstag 28. Oktober 2021, 11:10
von __deets__
Das ist doch das gleiche Problem wie beim letzten mal. Warum der neue Post?
Deine Vermutung ist falsch. Das die Queue blockiert ist schon richtig, denn wenn nichts da ist, kannst du eh auch nichts anderes machen, als wieder zu pruefen, ob etwas angekommen ist. Das verschwendet dann einfach nur CPU-Zyklen, ohne Wert.
Das ganze scheint ausserdem eh nur mit einer Datei umgehen zu koennen, denn wait_for_file beendet sich, wenn schon ein ein einziges File gefunden wurde.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Donnerstag 28. Oktober 2021, 11:26
von __deets__
So, das hier ist ein eigenstaendiges Beispiel, das funktioniert. Als erstes Argument an das Skript bekommt es den Pfad, den es ueberwachen soll.
Code: Alles auswählen
import sys
import time
import queue
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import (
QObject,
QThread,
pyqtSignal,
pyqtSlot,
)
class NewFileHandler(FileSystemEventHandler):
def __init__(self, q, *a, **k):
super().__init__(*a, **k)
self._q = q
def on_created(self, event):
self._q.put(event)
class Worker(QObject):
new_file = pyqtSignal(str)
def __init__(self, path):
super().__init__()
self._q = queue.Queue()
observer = Observer()
handler = NewFileHandler(self._q)
observer.schedule(handler, path=path, recursive=True)
# starts a background thread! Thus we need to wait for the
# queue to receive the events in work.
observer.start()
def work(self):
while True:
event = self._q.get()
if event.event_type == "created" and event.src_path.lower().endswith(".hdf5"):
self.new_file.emit(event.src_path)
class GuiObject(QObject):
def receive_hdf5_file(self, path):
print("receive_hdf5_file", path)
def main():
thread = QThread()
worker = Worker(sys.argv[1])
worker.moveToThread(thread)
thread.started.connect(worker.work)
thread.start()
gui_object = GuiObject()
# Important, this connection needs to happend *AFTER* the
# moveToThread!
worker.new_file.connect(gui_object.receive_hdf5_file)
app = QApplication(sys.argv)
app.exec_()
if __name__ == '__main__':
main()
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Freitag 29. Oktober 2021, 11:50
von pyhill00
__deets__ hat geschrieben: Donnerstag 28. Oktober 2021, 11:10
Das ganze scheint ausserdem eh nur mit einer Datei umgehen zu koennen, denn wait_for_file beendet sich, wenn schon ein ein einziges File gefunden wurde.
Das ist was ich versuche zu lösen. Dein Beispiel ist schon sehr hilfreich (vielen Dank dafür) aber das einzige Ding, das ich nicht lösen kann, ist, dass `wait_for_file` noch für weitere Daten suchen soll. In der `run()` Funktion gibt es `self.listener.wait_for_file()`, das noch "listening" soll aber nach einer Datei hört es auf.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Freitag 29. Oktober 2021, 12:07
von __deets__
Weil du das so programmiert hast. Das ist alles sehr konvolut & ich würde von meinem Beispiel ausgehen, das belegbar Signale verschickt wenn eine Datei angelegt wird. Denn einen Weg das bestehende umzumodeln kann ich nicht erkennen.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 18:23
von pyhill00
Danke für die Hilfe. Ich habe Vorschritt gemacht aber der neue Code hat das gleiche Problem: neue Dateien werden nicht anerkannt. Hier ist der Code:
Code: Alles auswählen
thread = QThread(parent=self)
print('try to connect to event service ...')
worker = watchdog_search.Worker("/home/xxx/Desktop/xxx/MPQ/test_image_analyzer_files/Test_Data/")
worker.moveToThread(thread)
thread.started.connect(worker.work)
thread.start()
worker.new_file.connect(self.on_finished_run)
Code: Alles auswählen
class NewFileHandler(FileSystemEventHandler):
def __init__(self, q, *a, **k):
super().__init__(*a, **k)
self._q = q
def on_created(self, event):
self._q.put(event)
class Worker(QObject):
new_file = pyqtSignal(str,str)
def __init__(self, path):
super().__init__()
self._q = queue.Queue()
observer = Observer()
handler = NewFileHandler(self._q)
observer.schedule(handler, path=path, recursive=True)
# starts a background thread! Thus we need to wait for the
# queue to receive the events in work.
observer.start()
def work(self):
max_retry_count = 3500 # for test purposes now but want to set an upper bound on verifying a file is finished.
retry_interval_seconds = .01 # every hundreth it will try the file to see if it finished writing
retry_count = 0
event = self._q.get()
while True:
#event = self._q.get()
try:
file = h5py.File(event.src_path, "r")
file.close()
self.new_file.emit(event.src_path, os.path.basename(event.src_path))
break # return file_path, file_name
except OSError:
if retry_count < max_retry_count:
retry_count += 1
print(f"h5 file <{event.src_path}> is locked, retrying {retry_count}/{max_retry_count}")
time.sleep(retry_interval_seconds)
else:
print(f"h5 file <{event.src_path}> reached max retry count, skipping")
except Exception as err:
print(f"Got unexpected Error <{type(err).__name__}> while opening <{event.src_path}> ")
traceback.print_exc()
Ein Paar DInge:
1. Ich musste `event = self._q.get()` aus der while Schleife tun, sodass es funktionieren konnte.
2. Wie du wieder siehst, habe ich dieses `try` hinzugefügt und `event.event_type == "created"` entfernt. Der Grund dafür, ist, dass `event.event_type == "created"` mit `.hdf5` Dateien nicht funktioniert. `hdf5` Dateien brauchen eine bestimmt Zeit, um verwendet zu werden. Ohne diese Zeit wird `event.event_type == "created"` eine nicht fertig geschriebene Datei zum Programm weiterschicken aber dann nichts wird funktionieren. Wenn ich dann dieses `try` hinzugefügt habe, hat das Programm wieder funktioniert allerdings nur mit einer Datei (wie am Anfang). Das ergibt natürlich Sinn -- `try` macht ein `break`. Ich habe versucht dieses Problem mit einer neuen Klasse zu lösen aber meine Idee hat nicht geklappt. Hier ist meine Idee:
Code: Alles auswählen
class NewFileHandler(FileSystemEventHandler):
def __init__(self, q, *a, **k):
super().__init__(*a, **k)
self._q = q
def on_created(self, event):
self._q.put(event)
class Worker(QObject):
new_file = pyqtSignal(str,str)
def __init__(self, path):
super().__init__()
self._q = queue.Queue()
observer = Observer()
handler = NewFileHandler(self._q)
observer.schedule(handler, path=path, recursive=True)
self.warte = Wait()
# starts a background thread! Thus we need to wait for the
# queue to receive the events in work.
observer.start()
def work(self):
while True:
event = self._q.get()
if self.warte.waitt(event) and event.src_path.lower().endswith(".hdf5"):
self.new_file.emit(event.src_path, os.path.basename(event.src_path))
class Wait():
def __init__(self):
self.max_retry_count = 3500 # for test purposes now but want to set an upper bound on verifying a file is finished.
self.retry_interval_seconds = .01 # every hundreth it will try the file to see if it finished writing
self.retry_count = 0
def waitt(self, event):
try:
file = h5py.File(event.src_path, "r")
file.close()
return True
except OSError:
if self.retry_count < self.max_retry_count:
self.retry_count += 1
print(f"h5 file <{event.src_path}> is locked, retrying {self.retry_count}/{self.max_retry_count}")
time.sleep(self.retry_interval_seconds)
return False
else:
print(f"h5 file <{event.src_path}> reached max retry count, skipping")
return False
except Exception as err:
print(f"Got unexpected Error <{type(err).__name__}> while opening <{event.src_path}> ")
traceback.print_exc()
return False
Die `while True` Schleife macht aber keine Schleife. Ich habe ein `print("aaaa")vor der if-Schleife getan und es wird nur einmal geprintet. Ich verstehe nicht, warum das nicht klappt.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 19:11
von __deets__
Was machst du denn da alles in dieser Methode? Warum schickst du nicht einfach das Signal? Was macht dieses Monstrum an code? Und was glaubst du ist die Wirkung eines breaks in einer Schleife?
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 19:13
von __blackjack__
@pyhill00: Natürlich funktioniert das nur einmal wenn Du nur *einmal* *vor* der Schleife ein Ereignis aus der Queue holst. Warum hast Du das vor die Schleife verschoben?
Und hör mal auf dem komischen Impuls nachzugeben tausend neue sinnfreie Trivialklassen zu basteln. Das ist Python und nicht Java.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 20:01
von pyhill00
@__deets__ ich habe klar in der Post geschrieben was der Code mit "try" macht und ich habe auch erklärt, dass es nicht gut ist, break zu benutzen aber sonst wird die while Schleife im try bleiben.
@__blackjack__ das war nur zum Debugging. Es soll in der Schleife sein.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 20:15
von __blackjack__
@pyhill00: Was meinst Du mit „sonst wird die Schleife im ``try`` bleiben“? Soll sie doch. Nur halt nicht immer mit dem selben `event`, also pack das abfragen der Queue da wieder in die Schleife.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 20:31
von pyhill00
@__blackjack__ das habe ich schon gemacht:
Code: Alles auswählen
while True:
event = self._q.get()
while True:
try:
file = h5py.File(event.src_path, "r")
file.close()
self.new_file.emit(event.src_path, os.path.basename(event.src_path))
print("a")
# break
except OSError:
if retry_count < max_retry_count:
retry_count += 1
print(f"h5 file <{event.src_path}> is locked, retrying {retry_count}/{max_retry_count}")
time.sleep(retry_interval_seconds)
else:
print(f"h5 file <{event.src_path}> reached max retry count, skipping")
except Exception as err:
print(f"Got unexpected Error <{type(err).__name__}> while opening <{event.src_path}> ")
traceback.print_exc()
Aber ja eben: es soll nur einmal ein event schicken aber es hört nicht auf das erste event zu schicken.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 20:46
von __deets__
Es gibt kein Break in try/except. Wenn das stimmte, hätte man hier eine endlose Ausgabe.
Hat man aber nicht. Darum ist auch klar, warum diese while Schleife sinnlos ist. Das ist also nicht nur nicht gut, es ist falsch.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 20:51
von __deets__
Und nochmal eine Anmerkung zu deinem HDF5-Problem: das hat erstmal mit HDF5 nichts zu tun. Sondern einfach damit, dass es kein Event für “fertig geschrieben” gibt. Das könnte auch eine Datei mit nur einem Buchstaben drin sein. Wenn der erst nach 10 Minuten nach dem öffnen geschrieben wird.
Um sowas zu lösen, macht man entweder atomare Umbenennungen, wenn man Kontrolle über den schreibprozess hat. Hast du die?
Oder man steckt die Kandidaten in eine Datenstruktur, und der sie dann periodisch geprüft werden. Mit einem Timer, der da regelmäßig reinschaut. Nicht so einen Monster-Verhau aus drölfzig Klassen.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 21:01
von pyhill00
__deets__ hat geschrieben: Montag 1. November 2021, 20:51
Um sowas zu lösen, macht man entweder atomare Umbenennungen, wenn man Kontrolle über den schreibprozess hat. Hast du die?
Ne habe ich nicht.
Dann die Idee mit der Datenstruktur. Kannst du mir einen Tipp geben, wie ich damit anfangen soll?
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 21:09
von __deets__
Zb ein Wörterbuch, mit Schlüssel Namen der Datei, und Wert die Anzahl der Versuche, die man probiert hat, die Datei zu öffnen. Wenn die eine schwellwert übersteigt, wird der Eintrag einfach entfernt. Genauso wie bei Erfolg, nur das dann die Datei zusätzlich per weiterem Signal als “kann geöffnet werden” vermeldet wird. Und diese Datenstruktur prüft man eben via QTimer alle paar Sekunden ab.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 21:53
von pyhill00
Die Schwierigkeit ist zu überprüfen, wann eine Datei fertig ist. Mit deiner Methode kann es passieren, dass eine Datei, die nicht fertig ist, geschickt wird. Deswegen habe ich dieses "Monstrum an Code" geschrieben habe: es testet genau wenn eine Datei fertig ist (natürlich ist das Problem, dass es nicht funktioniert, wie ich es will)
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Montag 1. November 2021, 22:02
von __deets__
Das habe ich schon verstanden. Und deine Schlussfolgerung stimmt nicht. Es geht schlicht darum, die Generierung von Kandidaten aus dem created event sauber zu trennen von der Überprüfung der Kandidaten, bis sie wahlweise aussortiert oder eben als ok vermeldet werden. Statt das alles in einen “big ball of mud” zu rollen, der wie du ja feststellst, nicht tut, was er tun soll.
Es gibt übrigens auch close Events. Die wären ggf ein besseres Signal. Das hängt natürlich letztlich vom Erzeugungsprozess ab. Der kann natürlich auch pathologische Zugriffsmuster haben, so das man nur heuristisch weiterkommt, wie du das ja auch machst.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Mittwoch 3. November 2021, 08:38
von pyhill00
Es funktioniert jetzt. Ich habe den else Teil von try verwendet:
Code: Alles auswählen
while True:
event = self._q.get()
max_retry_count = 3500 # for test purposes now but want to set an upper bound on verifying a file is finished.
retry_interval_seconds = .01 # every hundreth it will try the file to see if it finished writing
retry_count = 0
if event.event_type == "created" and event.src_path.lower().endswith(".hdf5"):
while True:
try:
file = h5py.File(event.src_path, "r")
file.close()
except OSError:
if retry_count < max_retry_count:
retry_count += 1
print(f"h5 file <{event.src_path}> is locked, retrying {retry_count}/{max_retry_count}")
time.sleep(retry_interval_seconds)
else:
print(f"h5 file <{event.src_path}> reached max retry count, skipping")
break # <--- looks useful here
except Exception as err:
print(f"Got unexpected Error <{type(err).__name__}> while opening <{event.src_path}> ")
traceback.print_exc()
else:
self.new_file.emit(event.src_path, os.path.basename(event.src_path))
break
Danke für die Hilfe __deets__! Dein Code war sehr hilfreich.
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Mittwoch 3. November 2021, 11:27
von __blackjack__
@pyhill00: Ich würde aus dem ``while`` ein ``for`` machen und Du behandelst unerwartete Ausnahmen in einer Art und Weise dass da leicht eine Endlosschleife entstehen kann. Und zwar eine die richtig CPU verbrät weil die ohne Wartezeit immer wieder versucht die Datei zu öffnen.
Warum werden bei dem Signal so redundante Daten gesendet? Der Pfad mit Dateiname und dann nochmal nur der Dateiname? Der steckt doch im Pfad mit Dateiname bereits drin.
Ungetestet:
Code: Alles auswählen
for event in iter(self._q.get, None):
# for test purposes now but want to set an upper bound on verifying
# a file is finished.
max_retry_count = 3500
# every hundreth it will try the file to see if it finished writing
retry_interval_seconds = 0.01
if (
event.event_type == "created"
and event.src_path.lower().endswith(".hdf5")
):
for retry_count in range(1, max_retry_count + 1):
try:
h5py.File(event.src_path, "r").close()
except OSError:
print(
f"h5 file {event.src_path!r} is locked, retrying"
f" {retry_count}/{max_retry_count}"
)
except Exception as error:
print(
f"Got unexpected Error <{type(error).__name__}> "
f"while opening {event.src_path!r}"
)
traceback.print_exc()
#
# TODO Maybe stop retrying here‽
#
else:
#
# TODO Why those redundant values? Why not just the
# first value?
#
self.new_file.emit(
event.src_path, os.path.basename(event.src_path)
)
break
time.sleep(retry_interval_seconds)
else:
print(
f"h5 file {event.src_path!r} reached max retry count,"
f" skipping"
)
Re: Fehler bei der Verwendung von Watchdog und Qt zum Offenhalten einer Queue vor/nach dem Senden der ersten Datei
Verfasst: Samstag 20. November 2021, 16:14
von pyhill00
Hallo wieder,
ich habe einen Bug entdeckt. Erstmal funktioniert das .hdf5 Datei Hochladen gut. Hier ist ein normales Ergebnis vom Terminal:
Code: Alles auswählen
running API pyqt5
using configuration at imageanalyser/qimageanalyser/image_analyzer.conf
no Pyro installed. Use dummy event handler.
{'coordinates': True, '_actions': {'home': <PyQt5.QtWidgets.QAction object at 0x7f8681235a60>, 'back': <PyQt5.QtWidgets.QAction object at 0x7f8681235af0>, 'forward': <PyQt5.QtWidgets.QAction object at 0x7f8681235b80>, 'pan': <PyQt5.QtWidgets.QAction object at 0x7f8681235ca0>, 'zoom': <PyQt5.QtWidgets.QAction object at 0x7f8681235dc0>, 'configure_subplots': <PyQt5.QtWidgets.QAction object at 0x7f8681235d30>, 'edit_parameters': <PyQt5.QtWidgets.QAction object at 0x7f8681235ee0>, 'save_figure': <PyQt5.QtWidgets.QAction object at 0x7f868123f040>}, 'locLabel': <PyQt5.QtWidgets.QLabel object at 0x7f8681235f70>, 'canvas': <qimageanalyser.mplwidget.MplCanvas object at 0x7f8688935940>, '_nav_stack': <matplotlib.cbook.Stack object at 0x7f868123d850>, '_lastCursor': <Cursors.POINTER: 1>, '_id_press': 2, '_id_release': 3, '_id_drag': 4, '_pan_info': None, '_zoom_info': None, 'mode': <_Mode.NONE: ''>}
try to connect to event service ...
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (3rd copy).hdf5> is locked, retrying 1/350
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (3rd copy).hdf5> is locked, retrying 2/350
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (3rd copy).hdf5> is locked, retrying 3/350
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (3rd copy).hdf5> is locked, retrying 4/350
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (3rd copy).hdf5> is locked, retrying 5/350
finished run test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (3rd copy).hdf5 2021_08_10_13_43_29 (3rd copy).hdf5
<HDF5 file "2021_08_10_13_43_29 (3rd copy).hdf5" (mode r+)>
analyze_image
xmean 135.47
xstd 41.31
xmean 148.42
xstd 41.17
mass: 3.81923985318e-26 [kg] size: 0.0002074740400778919 [m] tof: 0.01 [s]
mass: 3.81923985318e-26 [kg] size: 0.000122395198908796 [m] tof: 0.01 [s]
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (4th copy).hdf5> is locked, retrying 1/350
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (4th copy).hdf5> is locked, retrying 2/350
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (4th copy).hdf5> is locked, retrying 3/350
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (4th copy).hdf5> is locked, retrying 4/350
h5 file <test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (4th copy).hdf5> is locked, retrying 5/350
finished run test_image_analyzer_files/Test_Data/2021_08_10_13_43_29 (4th copy).hdf5 2021_08_10_13_43_29 (4th copy).hdf5
<HDF5 file "2021_08_10_13_43_29 (4th copy).hdf5" (mode r+)>
analyze_image
xmean 135.47
xstd 41.31
xmean 148.42
xstd 41.17
mass: 3.81923985318e-26 [kg] size: 0.0002074740400778919 [m] tof: 0.01 [s]
mass: 3.81923985318e-26 [kg] size: 0.000122395198908796 [m] tof: 0.01 [s]
Ich habe da zwei Bilder hinzugefügt und das Programm hat geklappt. Ich habe das Programm beendet und dann habe ich Programm etwa fünf mal mehr laufen lassen (also Bilder in den Ordner tun, und testen, ob ich noch Bilder sehen kann und dann das Programm beendet). Aber dann nach etwa fünf Mal funktioniert das Programm nicht mehr. Jetzt bekomme ich das gleiche, jedes mal, das ich das Programm laufen lasse und neue Bilder hinzufüge:
Code: Alles auswählen
running API pyqt5
using configuration at imageanalyser/qimageanalyser/image_analyzer.conf
no Pyro installed. Use dummy event handler.
{'coordinates': True, '_actions': {'home': <PyQt5.QtWidgets.QAction object at 0x7f8681235a60>, 'back': <PyQt5.QtWidgets.QAction object at 0x7f8681235af0>, 'forward': <PyQt5.QtWidgets.QAction object at 0x7f8681235b80>, 'pan': <PyQt5.QtWidgets.QAction object at 0x7f8681235ca0>, 'zoom': <PyQt5.QtWidgets.QAction object at 0x7f8681235dc0>, 'configure_subplots': <PyQt5.QtWidgets.QAction object at 0x7f8681235d30>, 'edit_parameters': <PyQt5.QtWidgets.QAction object at 0x7f8681235ee0>, 'save_figure': <PyQt5.QtWidgets.QAction object at 0x7f868123f040>}, 'locLabel': <PyQt5.QtWidgets.QLabel object at 0x7f8681235f70>, 'canvas': <qimageanalyser.mplwidget.MplCanvas object at 0x7f8688935940>, '_nav_stack': <matplotlib.cbook.Stack object at 0x7f868123d850>, '_lastCursor': <Cursors.POINTER: 1>, '_id_press': 2, '_id_release': 3, '_id_drag': 4, '_pan_info': None, '_zoom_info': None, 'mode': <_Mode.NONE: ''>}
try to connect to event service ...
Also es geht nicht mehr in die while-Schleife uzw. Weißt jemand woran es liegen kann. Vielleicht muss ich genau den Thread schließen? Oder vielleicht ist es wohl das Problem wie __blackjack__ erwähnt hat?
Hier ist der Code bzgl. dieses Problemes:
Code: Alles auswählen
thread = QThread(parent=self) #this part is in the DesignerMainWindow() __init__() shown below
print('try to connect to event service ...')
worker = watchdog_search.Worker("/home/test_image_analyzer_files/Test_Data/")
worker.moveToThread(thread)
thread.started.connect(worker.work)
thread.start()
worker.new_file.connect(self.on_finished_run)
def run_app():
try:
# first try to get an existing app
app = QtGui.QApplication.instance()
reuseapp = True
if app is None:
app = QtGui.QApplication(sys.argv)
reuseapp = False
except:
pass
dmw = DesignerMainWindow()
dmw.show()
return dmw, app, reuseapp
if __name__ == "__main__":
dmw, app, reuseapp = run_app()
if "app" in globals() and not reuseapp:
sys.exit(app.exec_())
`watchdog_search`:
Code: Alles auswählen
import time
import traceback
import os
import h5py
import queue
from typing import Union
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler, DirCreatedEvent, FileCreatedEvent
from .tools.qt import QtCore
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import (
QObject,
QThread,
pyqtSignal,
pyqtSlot,
)
class NewFileHandler(FileSystemEventHandler):
def __init__(self, q, *a, **k):
super().__init__(*a, **k)
self._q = q
def on_created(self, event):
self._q.put(event)
class Worker(QObject):
new_file = pyqtSignal(str,str)
def __init__(self, path):
super().__init__()
self._q = queue.Queue()
observer = Observer()
handler = NewFileHandler(self._q)
observer.schedule(handler, path=path, recursive=True)
# starts a background thread! Thus we need to wait for the
# queue to receive the events in work.
observer.start()
def work(self):
while True:
event = self._q.get()
max_retry_count = 350 # for test purposes now but want to set an upper bound on verifying a file is finished.
retry_interval_seconds = .01 # every hundreth it will try the file to see if it finished writing
retry_count = 0
if event.event_type == "created" and event.src_path.lower().endswith(".hdf5"):
while True:
try:
file = h5py.File(event.src_path, "r")
file.close()
except OSError:
if retry_count < max_retry_count:
retry_count += 1
print(f"h5 file <{event.src_path}> is locked, retrying {retry_count}/{max_retry_count}")
time.sleep(retry_interval_seconds)
else:
print(f"h5 file <{event.src_path}> reached max retry count, skipping")
break # <--- looks useful here
except Exception as err:
print(f"Got unexpected Error <{type(err).__name__}> while opening <{event.src_path}> ")
traceback.print_exc()
else:
self.new_file.emit(event.src_path, os.path.basename(event.src_path))
break