Stausmeldungen übergeben

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
Benutzeravatar
Blackshie
User
Beiträge: 13
Registriert: Mittwoch 17. Januar 2018, 15:45

Hallo,

Ich habe eine Funktion welche lange und verschiedene Berechnungen durchführt.
Zwischendurch möchte ich mir Statusmeldungen dazu ausgeben lassen.
Diese sollen an einem anderem Ort abgegriffen werden um sie dann zum Beispiel in einer GUI darstellen zu können.
Um meine Funktion möglichst allgemein zu halten wäre es wenig geschickt diese auf meine GUI anzupassen.

Eventuell gibt es sowas wie einen gemeinsamen Pool in dem man schreiben und wieder daraus lesen könnte.
Oder ich schreibe sie mit print in die Konsole und lese dann auch wieder davon.
Dazu habe ich aber noch nichts gefunden.

Mir ist noch keine funktionierende Lösung eingefallen.


Ich füge noch einen vereinfachten Beispielcode an meinen Beitrag, damit es ersichtlicher wird was ich meine.

Code: Alles auswählen

def Berechnungen():
    
    summe = 0
    
    # Statusmeldung
    print("Wird gestartet...")
    
    # Statusmeldung
    print("Summe wird gebildet...")    
    
    # Berechnungen
    for i in range(25):
        
        summe += i
        
    # Statusmeldung
    print("Produkt wird berechnet...")
    
    # Berechnungen
    for i in range(1, 10):
        
        summe *= i

    # Statusmeldung
    print("Fertig...")
    
    return summe
    

def Start():
    
    # Von hier aus wird die Funktion aufgerufen
    # Von hier sollte auch die GUI gezeichnet und mit den Statusmeldungen versehen werden
    ergebnis = Berechnungen()
    
    print(ergebnis)


Start()
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst einfach ein callable reingeben als Argument, mit dem dann Fortschritte gemeldet werden. Die GUI kann dann eine Implementierung einkippen, die dann eine entsprechende Reaktion ausloest.

Code: Alles auswählen

def arbeit(argument, anderes_argument, status_callback=lambda status: None):
      status_callback(("start")
      for i in range(100):
             status_callback("progress") 
             ...
      status_callback("end")
          
Das default-Argument sorgt dafuer, das nix passiert, wenn du die Funktion ohne Status-Meldung aufrufst. Natuerlich ist deiner Fantasie bei der Gestalt der Meldungen keine Grenze gesetzt.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1011
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Mit Generatoren könntest du den Kontrollfluss zurück geben.
In einer anderen Funktion hast du dann eine Art Sheduler, der die Tasks ausführt.
Zwischenergebnisse kann man auch ausgeben. Dazu müsste man den Rückgabewert
von next(task) auswerten. Der Generator muss dann aber auch mit yield etwas zurückgeben.
Ein yield oder return ohne weitere Angaben, liefert das Objekt None implizit zurück.

Code: Alles auswählen

from collections import deque


def berechnungen(start):
    yield
    summe = start
    print("Wird gestartet...")
    yield
    print("Summe wird gebildet...")
    yield   
    for i in range(25):
        summe += i
    print("Produkt wird berechnet...")
    yield
    for i in range(1, 10):
        summe *= i
    print("Fertig...")
    return summe

def loop(tasks):
    while tasks:
        task = tasks.popleft()
        try:
            next(task)
        except StopIteration as result:
            print('Result found:', result)
        else:
            tasks.append(task)

tasks = deque([berechnungen(5), berechnungen(20)])
loop(tasks)
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Dead_Eye was mir daran nicht gefaellt ist die Menge an Infrastruktur die ploetzlich notwendig wird, nur weil man man einen Status melden moechte. Der Aufrufer muss ein ganz anderes Protokoll fahren.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@Blackshie: für Statusmeldungen benutzt man logging. Die Mächtigkeit dieses Ansatzes kannst Du z.B. hier lesen. Normalerweise werden Log-Nachrichten einfach in der Konsole ausgegeben. Wenn Du die Nachrichten in einer GUI haben möchtest, bietet es sich an einen QueueHandler zu benutzen und in der GUI regelmäßig die Queue nach neuen Meldungen abzufragen.

Alle händischen Eigenentwicklungen führen nur dazu, dass Du Teile von logging nachprogrammierst und im Endeffekt doch nicht so flexibel bist.
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: da muss ich widersprechen. Ein Status wie zB ein Download-Balken ist ein User-Feature. Logging dazu zu missbrauchen bedeutet, das zB die Konfiguration eben dieses loggings ein user-feature zerstoert. Wohl kaum eine wuenschenswerte Eigenschaft. Genausowenig ist die Erzeugung und Ruecktransformation von Strings eine gute Idee. Aber das ist der Datentyp, mit logging primaer zu tun hat. Und last but not least ist die Komplexitaet von hierarchischen Handlern verruehrt mit Nebenlaeufigkeit etc. auch nicht gerade simpel zu handhaben.

Nachtrag: gerade gesehen, das du den Queue-Handler vorschlaegst. Kannte ich nicht, der nimmt natuerlich die Implementierungsdetails aus der Gleichung. Ich bleibe trotzdem dabei: das ist nicht der vorgesehene Einsatzzweck fuer logging.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: die Meldungen, die Blackshie in seinem Code-Beispiel hat, sind typische Logging-Meldungen. Und so wie ich es verstanden habe, will der OP einfach die Meldungen in einem GUI-Fenster haben. Wenn man generelle Funktionen schreiben will, ist es gut sich an bewährte Standards zu halten.
Benutzeravatar
Blackshie
User
Beiträge: 13
Registriert: Mittwoch 17. Januar 2018, 15:45

Danke für euren vielen Antworten.

@__deets__: Danke fürs erste ist deine Lösung ausreichend.

@Sirius3: Ich werde mir das Logging Modul bei Zeiten auch mal anschauen. Scheint auf jeden Fall mächtig zu sein
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sirius3 hat geschrieben:@__deets__: die Meldungen, die Blackshie in seinem Code-Beispiel hat, sind typische Logging-Meldungen. Und so wie ich es verstanden habe, will der OP einfach die Meldungen in einem GUI-Fenster haben. Wenn man generelle Funktionen schreiben will, ist es gut sich an bewährte Standards zu halten.
Wenn es sich um ein log-Fenster handelt, wie man das zB in einer IDE beim build oder aehnlichem zu sehen bekommt, bin ich vollkommen bei dir. Das ist aber glaube ich ein Sonderfall, viele Fortschrittsanzeigen sind in Form von Spinnern, diskreten Schritten oder aehnlichem. Da waere der logging-Ansatz IMHO verfehlt. Letztlich kann der TE das natuerlich nur fuer sich entscheiden.
Benutzeravatar
pixewakb
User
Beiträge: 1405
Registriert: Sonntag 24. April 2011, 19:43

Sirius3 hat geschrieben:@__deets__: die Meldungen, die Blackshie in seinem Code-Beispiel hat, sind typische Logging-Meldungen. Und so wie ich es verstanden habe, will der OP einfach die Meldungen in einem GUI-Fenster haben. Wenn man generelle Funktionen schreiben will, ist es gut sich an bewährte Standards zu halten.
An das logging-Modul hatte ich auch zuerst gedacht.

@Blackshie: Ich habe eine vergleichbare Problemstellung, d. h. ich habe Agenten laufen, die Aufgaben erledigen und manchmal kommt es vor, dass die aus irgendeinem Grund in der Arbeit einschlafen (ich vermute, dass nicht genug Arbeitsspeicher oder Internetverbindung zur Verfügung steht), weshalb ich sie dann beenden und neustarten muss. Bei manchen passiert auch lange nichts und ohne die Statusmeldung könnte ich nicht sehen, was gerade passiert und dass sie noch laufen.

Ich habe es für mich wie folgt gelöst:

Ich schreibe die logging-Nachrichten in eine log-Datei, falls ich verfolgen will, was passiert, dann öffne ich die Datei in Notepad++, was bei Änderungen der Datei und Fokus-Wechsel nachfragt, ob es nachladen soll. Das ist meine GUI-Lösung, möglicherweise reicht das für dich auch.
Antworten