2 oder mehr Aufgaben gleichzeitig

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
Streifenhase1
User
Beiträge: 90
Registriert: Dienstag 22. Mai 2018, 07:15

Ich Werte permanent, aller 300ms Werte aus einer SPS aus und zähle damit einen Wert.

wenn nun ein bestimmtes Signal kommt wird über ein Netzwerk ein Bild geladen und angezeigt.

dieses dauert relativ lange 5 sec.

und in dieser Zeit steht nun der Wert (wird mit tkinter angezeigt) solange bis das Bild geladen wurde und macht beim zählen dann einen großen Sprung.

Ist es möglich das auswerten der SPS und aktualisieren des Tkinter ohne diese Unterbrechung umzusetzen und wenn wie.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Streifenhase1: Das `threading`-Modul – und all die Probleme die das dann mit sich bringt. Also das man die GUI nur aus dem Thread heraus ändern darf in dem die `mainloop()` läuft. Das löst man dann üblicherweise mit Queues zwischen den Threads und `after()` in `tkinter` wo man dann regelmässig prüft ob das Bild in der Queue steckt und angezeigt werden kann. Und der Thread der das Bild lädt, steckt das dann in die Queue wenn er fertig ist.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Streifenhase1
User
Beiträge: 90
Registriert: Dienstag 22. Mai 2018, 07:15

ok danke also mit 'threading' versuche ich es gerade...

kann ich 'threading' mit after kombinieren oder macht man das mit while?

weil wenn ich die Funktion mit after wieder Aufrufe ist es dann kein eigener Thread mehr

wenn ich
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Im Thread benutzt du while, und fragst deine SPS ab. Den Zaehlerstand kommunizierst zu zB ueber eine queue, und mit after fragst du die regelmaessig ab. Wenn es zwischendurch mal 5 Sekunden dauert, ein Bild zu laden, macht das nichts, denn die queue hat die anderen Messergebnisse gespeichert. Und ganz verrueckt wird es natuerlich, wenn du die Abfrage des Bildes *auch* in einem (anderen!) Thread machst, und ebenfalls kommunizierst, dass das Bild fertig ist mit einer Queue. Auf die Art und Weise bleibt deine GUI immer ansprechbar.
Streifenhase1
User
Beiträge: 90
Registriert: Dienstag 22. Mai 2018, 07:15

Ok. Danke für die Tips also mit dem Laden des Bildes über Thread funktioniert schon mal so einigermaßen.

Jetzt aber noch mal was anderes...

Ich nutze Python auf Windows(7) und habe im Netzwerk einen Rechner mit XP (geht leider nicht anders) den Freigegebenen Ordner vom XP Rechner habe ich auf dem Windows 7 als ein Laufwerk zugewiesen. Der zugriff Funktioniert recht schnell bzw. das öffnen der Bilder.

wenn ich aber das Bild bei Python lade durch Angabe des Pfades des Netzwerklaufwerkes dauert es eben so lange. (Das Verzeichnis wird nach der neusten Datei durchsucht und diese dann geladen). Wenn ich das selbe lokal mache geht es sehr schnell.

gibt es da eine andere Möglichkeit für den Zugriff auf das Netzwerklaufwerk über python und der IP?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Streifenhase1: Es kann sein, dass da ungünstig in kleinen Häppchen gelesen wird. Kannst Du mal den Code zeigen?
Du weißt, dass XP mit freigegebenem Ordner offen ist wie ein Scheunentor? Das Netzwerk ist hoffentlich schön abgeschottet.
Streifenhase1
User
Beiträge: 90
Registriert: Dienstag 22. Mai 2018, 07:15

@Sirius3 also der XP hängt nicht im Internet und sind nur die 2 Rechner die miteinander verbunden sind.

der Code für die Bilder sieht etwa so aus... wobei "Z:\" das Netzwerk ist. Wie gesagt wenn ich es mit einem auf dem Rechner befindlichen Ordner mache gibt es keine Probleme und ist in Bruchteilen einer Sekunde geladen.

Code: Alles auswählen


def Defects_update(self):


    list_of_files = glob.glob("Z:\Bilder")
    if len(list_of_files) > 0:

        latest_file = max(list_of_files, key=os.path.getctime)
        found = latest_file
        print (found)
        time_string = datetime.datetime.fromtimestamp(os.stat(found).st_mtime)
        datum = time_string.strftime("%d.%m.%Y    %H:%M:%S")
        self.Pictur_date_threshold.set(datum)

        baseheight = 480
        im = Image.open(found)
        width, height = 480, 480
        wpercent = baseheight/height
        newwidth = width * wpercent
        newwidth = int(newwidth)
        newsize = (482, 482)
        imnew = im.resize(newsize, PIL.Image.ANTIALIAS)

        try:

            self.canvas.image = ImageTk.PhotoImage(imnew)
            self.canvas.itemconfig(self.Defects_image, image = self.canvas.image)


        except IOError:
            print ("close")
            pass

    else:

        found = "Data\NoPicture.bmp"
        self.Picture1_threshold.set("")

       baseheight = 480
       im = Image.open(found)
       width, height = 480, 480
                
       wpercent = baseheight/height
       newwidth = width * wpercent
       newwidth = int(newwidth)
       newsize = (482, 482)
       imnew = im.resize(newsize, PIL.Image.ANTIALIAS)
       self.canvas.image = ImageTk.PhotoImage(imnew)
       self.canvas.itemconfig(self.Defects_image, image = self.canvas.image)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Deine Einrückungen sind kaputt. Ich rate mal, wie das gemeint ist. Da hast Du 10 Zeilen Code im if- und else-Block, die identisch sind.

Wie viele Dateien hast Du denn? Von jedem die Zeit abzufragen dauert halt. Oder hast Du mal geschaut, wo die Zeit verschwendet wird?

Warum nennst Du `latest_file` in `found` um? `time_string` ist gar kein String.
`newwidth` wird gar nicht verwendet, damit auch nicht `width`, `wpercent`, `baseheight`, und `height`.

Bleibt das:

Code: Alles auswählen

def get_latest_file(path):
    return max(glob.glob(path), key=os.path.getctime)

def defects_update(self):
    try:
        filename = get_latest_file("Z:\Bilder")
        ctime = os.path.getctime(filename)
        datum = "{:%d.%m.%Y    %H:%M:%S}".format(
            datetime.datetime.fromtimestamp(ctime))
    except ValueError:
        found = r"Data\NoPicture.bmp"
        datum = ""

    self.Picture1_threshold.set(datum)
    newsize = (482, 482)
    imnew = im.resize(newsize, PIL.Image.ANTIALIAS)
    self.canvas.image = ImageTk.PhotoImage(imnew)
    self.canvas.itemconfig(self.defects_image, image=self.canvas.image)
Streifenhase1
User
Beiträge: 90
Registriert: Dienstag 22. Mai 2018, 07:15

Also ich habe jetzt 2 Threads laufen einer liest die SPS aus und der andere die Bilder. Jetzt brauche ich aber ein Signal der SPS, was ich in eine Queue schreibe.
der wert in der Queue kann "0" sein oder größer. Wenn der wert größer "0" ist soll das bild geladen werden.

Funktioniert aber leider nur 1x wenn der wert der Queue von "0" auf >0 springt und wieder auf "0" wir in einer Endlosschleife das Bild geladen.

Kann mir jemand helfen!?


anders würde es auch funktionieren wenn ich das letzte geladene Bild (Dateiname) mit dem Aktuellem Bild nach dem durchsuchen des Verzeichnisses (neuste Datei) vergleiche und nur lade wenn der Name anders ist.

Code: Alles auswählen

 def picture_update(self):
  
        while self.schnitt1.get() > 0 :

            try:                
                filename = max(glob.glob("Z:\Bilder), key=os.path.getctime)
                ctime = os.path.getctime(filename)
                datum = "{:%d.%m.%Y    %H:%M:%S}".format(datetime.datetime.fromtimestamp(ctime))

            except ValueError:
                filename = r"Data\NoPicture.bmp
                datum = ""
                
            self.Picture1_threshold.set(datum)
            newsize = (482, 482)
            imnew = filename.resize(newsize, PIL.Image.ANTIALIAS)
            self.canvas.image = ImageTk.PhotoImage(imnew)
            self.canvas.itemconfig(self.defects_image, image=self.canvas.image)
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Streifenhase1: Also mir wird aus der Beschreibung weder klar was Du willst, noch was im Code passiert.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Streifenhase1
User
Beiträge: 90
Registriert: Dienstag 22. Mai 2018, 07:15

Also es soll in einer while schleife die Queue

Code: Alles auswählen

self.schnitt1.get()  :

gelesen werden. Wenn der Wert der Queue "0" ist dann soll nichts passieren auser weiter die Queue lesen. Wenn deren Inhalt größer als 0 ist soll die Funktion ausgeführt werden.

Code: Alles auswählen

 try:                
     filename = max(glob.glob("Z:\Bilder), key=os.path.getctime)
     ctime = os.path.getctime(filename)
     datum = "{:%d.%m.%Y    %H:%M:%S}".format(datetime.datetime.fromtimestamp(ctime))

     except ValueError:
     filename = r"Data\NoPicture.bmp
     datum = ""
                
     self.Picture1_threshold.set(datum)
     newsize = (482, 482)
     imnew = filename.resize(newsize, PIL.Image.ANTIALIAS)
     self.canvas.image = ImageTk.PhotoImage(imnew)
     self.canvas.itemconfig(self.defects_image, image=self.canvas.image)
            



Wenn der Inhalt der Queue wieder "0" ist soll wieder nur die "Queue" abgefragt werden.


Hoffe jetzt ist es verständlicher
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Dann sollte aber der Wert aus der Queue nicht in die Bedingung für die while-Schleife sein. Wenn die Bedingung nicht mehr erfüllt ist, bricht die Schleife nämlich ab und wird gar nicht mehr ausgeführt.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sparrow: Das ist ja auch gut so, und die Bedingung ist hoffentlich ziemlich schnell nicht mehr erfüllt, denn in der Schleife wird an der GUI etwas geändert, das heisst die muss in den Thread sein in dem die `mainloop()` läuft. Darum verwirrt mich das ja auch so was da steht. Das sieht auf die eine oder andere Art falsch aus.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Streifenhase1
User
Beiträge: 90
Registriert: Dienstag 22. Mai 2018, 07:15

Hab es noch mal geändert aber ohne Erfolg.
Funktionier 1x und wenn "If schnitt > 0" erfolgt ist macht er keine abfrage mehr.

Code: Alles auswählen

def picture_update(self):
  
    while 1:
        self.schnitt1.get()
        schnitt = self.schnitt1
        
	if schnitt  > 0 :
            try:                
                filename = max(glob.glob("Z:\Bilder), key=os.path.getctime)
                ctime = os.path.getctime(filename)
                datum = "{:%d.%m.%Y    %H:%M:%S}".format(datetime.datetime.fromtimestamp(ctime))

            except ValueError:
                filename = r"Data\NoPicture.bmp
                datum = ""
                
    self.Picture1_threshold.set(datum)
    newsize = (482, 482)
    imnew = filename.resize(newsize, PIL.Image.ANTIALIAS)
    self.canvas.image = ImageTk.PhotoImage(imnew)
    self.canvas.itemconfig(self.defects_image, image=self.canvas.image)
            	            

habe noch ein andere Frage!

wenn diese Zeile im Programm ausgeführt wird

Code: Alles auswählen

 filename = max(glob.glob("Z:\Bilder), key=os.path.getctime)
 
kommt es gelegentlich zu Fehlern das der Pfad bzw. die Datei nicht gefunden wird und die Schleife bricht ab. Grund daführ ist das Schreiben und löschen von Dateien.

Wie könnte ich das beheben, z.B. wenn Datei nicht gefunden dann noch mal Prüfen
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Streifenhase1: aus den Schnipseln, die Du hier zeigt, wird überhaupt nicht klar, was Du da versuchst. Du hast also irgendwie einen Trigger, wann das Bild aktualisiert werden soll. Wie ist denn das mit Deiner Dateiablage synchonisiert? Und was soll das mit > oder == 0?

Zur Frage: genau, einfach nochmal versuchen, wenn es einen Fehler gibt.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Streifenhase1: Der gezeigte Code ist unsinnig oder nicht lauffähig, denn entweder ist `schnitt1` *immer* grösser oder *immer* kleiner 0, oder in Python 3 bekommst Du eine Ausnahme weil man `schnitt` (Queue oder was anderes mit `get()`-Methode) nicht auf diese Weise mit 0 vergleichen kann.

Wo läuft das denn überhaupt? Das kann/darf ja nicht in einem eigenen Thread laufen, denn dann dürfte der Code mit dem Ändern der GUI da nicht stehen.

Was kommen denn da überhaupt für Werte an? Was bedeuten die? Wie sieht das Muster in dem Datenstrom aus?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Streifenhase1
User
Beiträge: 90
Registriert: Dienstag 22. Mai 2018, 07:15

Also in einem Thread wir eine SPS in einer while schleife ausgelesen. Die Werte werden in Queue geschrieben.

Code: Alles auswählen

self.schnitt1.put(schnitt)
Müssen zwei Threads sein weil sonst immer etwas hängt da Über die SPS noch weitere werte angezeigt werden.

der gezeigte code wird als ein eigener Thread gestartet.
Die SPS gibt entweder "0" aus oder einen wert der aber "255" oder "455" oder auch ein anderer werte sein kann.

wenn ich es so durchlaufen lasse sehe ich die werte die die SPS ausgibt.

Code: Alles auswählen

def picture_update(self):
  
    while 1:
        self.schnitt1.get()
        schnitt = self.schnitt1
        print (schnitt)
        
	
Wenn nun die SPS "0" ausgibt soll nichts gemacht werden und wenn die "SPS" einen wert der größer als "0" ausgibt soll ein Verzeichniss nach der Aktuellsten Datei durchsucht werden und diese dann geladen werden.


Wie gesagt wenn die SPS von 0 auf ein anderen wert springt wird ein Bild geladen,

wenn die SPS aber 0 ausgibt wird trotdem immer wieder das Bild geladen, so wie als ober die "If" Abfrage nicht mehr erfolgt
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wenn grundsätzlich bei 0 nichts gemacht werden soll, dann braucht man die 0 ja auch nicht in die Queue schreiben, sondern nur die Werte bei denen etwas gemacht werden soll.

Wie wird denn `picture_update()` ausgeführt? Wenn das in einem Thread läuft, dann darf da die GUI nicht verändert werden, machst Du es doch kann sonst was passieren. Wenn es nicht in einem Thread läuft, dann blockiert die ``while``-Schleife die GUI. Also entweder ist der Code zum GUI-Ändern dort falsch, oder die Endlosschleife.

Wird denn tatsächlich immer das Bild neu geladen? Oder einfach nur auch weiterhin angezeigt auch wenn die SPS wieder 0 liefert? Und wenn das Bild laden lange/länger dauert als SPS-Werte geliefert werden, ist Dir klar, dass sich dann Werte in der Queue aufstauen die danach dann weiter abgearbeitet werden und letztlich dann zumindest zeitweise nichts mehr mit dem *aktuellen* Wert von der SPS zu tun haben‽
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten