funktionen in klassen / threads: mache ich das richtig?

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
jo_hb
User
Beiträge: 72
Registriert: Donnerstag 26. April 2007, 09:21

Donnerstag 14. Juni 2007, 19:29

Hallo,
ich kommen manchmal noch etwas durcheinander mit dem 'self' in klassen, und versuche mich ausserdem grad mit threads - ich habe hier das folgende:

Code: Alles auswählen

class xyz:
    def __init__(self):
        self.threadLock = 0
        self.daten = list()

    # ...

    def updateMarketPrices(self, market):
        for i in self.daten:
            # daten modifizieren
        # ...
        return

    def marketThread(self, market, timer):
        def thread(market, timer, lock):
            lock.acquire()
            self.updateMarketPrices(market)
            lock.release()
            time.sleep(timer)

        if self.threadLock == 0:
            self.threadLock = thread.allocate_lock()
            
        thread.start_new_thread(thread, market, timer, self.threadLock)
 
Ich habe es noch nicht ausprobieren können, weil mein ganzes programm drumrum noch weit von fertig ist - wollte nur schonmal wissen ob das so die Art ist wie man sowas machen würde? Also speziell im Hinblick auf die Benutzung des lock, und auf die Art wie ich die funktion 'thread' in die andere Funktion eingebaut habe (also ob alle 'self' da sind wo sie hingehören bzw, da _nicht_ sind wo sie auch nicht hingehören...)

Von aussen hätte ich dann eine Liste mit markets, und für jeden würde ich einmal xyz.marketThread aufrufen.

Achja, für den Fall das ich das mit dem lock _völlig_ falsch verstanden habe: Der Sinn soll sein, dass nicht zwei threads gleichzeitig 'self.daten' zu ändern versuchen, weil ich mir denke dass man das vielleicht nicht machen sollte?

Vielen Dank für eure Hilfe,
Jo
BlackJack

Donnerstag 14. Juni 2007, 19:37

Das `thread`-Modul ist relativ "low-level". Im Modul `threading` sind etwas komfortablere Objekte.

Und `self.threadLock` würde ich in der `__init__()` schon an ein `threading.Lock` binden. Und wenn verzögert initialisieren, dann bitte `None` als Platzhalter verwenden.

Die Namensgebung hält sich nicht an die üblichen Konventionen. Besonders fällt das beim Klassennamen auf -- den klein zu schreiben ist *sehr* ungewöhnlich.
jo_hb
User
Beiträge: 72
Registriert: Donnerstag 26. April 2007, 09:21

Donnerstag 14. Juni 2007, 19:53

danke blackjack. stimmt, könnte ich ja gleich schon im __init__ mit nem lock ausstatten, dann könnte ich mir das if ganz sparen...

Der klassenname ist nur ein platzhalter, damits hier nen kompletten code ergibt, in wirklichkeit heisst die anders - was stimmt denn sonst nicht mit der Namensgebung?

threading hab ich mir auch angeguckt, aber ich glaube ich brauche eigentlich nichts weiter als das lock. Ist denn mein Verständnis des lock richtig, von wegen damit die daten nicht durcheinanderkommen, oder könnte ich mir das lock womöglich ganz sparen?

Gruss,
Jo
BlackJack

Donnerstag 14. Juni 2007, 20:07

In PEP 0008 - Style Guide wird für Attribute und Funktionen worte_mit_unterstrichen statt mixedCase empfohlen.

Über die Threads aus `thread` hat man kaum Kontrolle. `threading.Threads` kann man zum Beispiel nach ihrem Zustand befragen, oder auf ihr Ende warten. Und ab Python 2.5 kann man `threading.Lock`\s mit der neuen ``with``-Anweisung verwenden, was den Code sicherer macht, falls der kritische Abschnitt durch eine Ausnahme verlassen wird.
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Freitag 15. Juni 2007, 09:36

Deine verwendung der Locks sieht schon mal gar nicht schlecht aus. In diesem Beispiel wäre es vielleicht noch sinnvoll, das Locken in die Methode "updateMarketPrices" zu verschieben, da in "thread" gar keine direkten Änderungen an den Daten vorgenommen werden, bzw. nur über "updateMarketPrices". Sollten noch weitere Änderungen hinter "updateMarketPrices" geschützt werden, kann man den jetzigen Aufbau so lassen.

Wie BlackJack ja schon meinte, solltest du ab 2.5 kritische Abschnitte mit dem with-Statement schützen. Falls du kein 2.5 zur Verfügung hast, kannst du dies auch mit einem try-finally-Konstrukt machen:

Code: Alles auswählen

lock.acquire()
try:
    self.updateMarketPrices(market)
finally:
    lock.release()
Das ist äquivalent zu der with-Variante. Wichtig ist, dass das "lock.acquire()" VOR dem try steht, da dir sonst bei einem fehlerhaften "acquire" alles um die Ohren fliegt.
Antworten