Warum funktioniert bei mir die Lock Funktion nicht, um andere Threads zu stoppen?

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo,

    ich möchte, das in einem Thread ein Programmbereich komplett ausgeführt

    wird und das in diesem Zeitraum keine anderen Threads aufgerufen werden.

    Das sollte ja eigentlich mit der Lock-Funktion funktionieren.

    In der Zeile 53 steht die Funktion tlock.acquire() und in der Zeile 65 tlock.release().

    Bis der Bereich dazwischen abgearbeitet ist, das dauert eine Weile.

    Der andere Thread (Testthread) läuft inzwischen aber munter weiter.

    Was mache ich falsch, sollte doch eigentlich ganz einfach sein?

    Gruß Reinhard

  • Warum funktioniert bei mir die Lock Funktion nicht, um andere Threads zu stoppen?? Schau mal ob du hier fündig wirst!

  • Das ist nicht, wie Thread-Locks funktionieren - siehe Python-Doku: https://docs.python.org/3/library/thre…ml#lock-objects

    Du hast IMHO nicht wirklich gut beschrieben, wie das Endergebnis aussehen soll (Threads werden nicht "aufgerufen" :conf:) - aber hier ist ein Beispiel, welches vielleicht das macht, was du erreichen willst:

    Ausgabe:

    In Zukunft am besten anstatt 74 Zeilen mäßigen Code zu posten, von dem nicht annähern die Hälfte etwas mit dem tatsächlichen Problem zu tun hat, bitte etwas Mühe geben und ein kompaktes Beispiel erstellen, mit dem sich das Problem auch ohne all deine Hardware reproduzieren lässt.

  • Hallo Linus,

    vielen Dank für deine Mühe!

    Ich arbeite das erst mal in Ruhe durch.

    Eigentlich habe ich es gemacht wie in diesem Video:

    Externer Inhalt www.youtube.com
    Inhalte von externen Seiten werden ohne deine Zustimmung nicht automatisch geladen und angezeigt.
    Durch die Aktivierung der externen Inhalte erklärst du dich damit einverstanden, dass personenbezogene Daten an Drittplattformen übermittelt werden. Mehr Informationen dazu haben wir in unserer Datenschutzerklärung zur Verfügung gestellt.

    Den Code hatte ich schon total eingeschrumpft, die ganze Benutzeroberfläche mit

    TKinter ist raus, allerdings ist das Programm wirklich unübersichtlich.

    Gruß Reinhard

  • #!/usr/bin/env python

    Python 2 hat in weniger als 6 Monaten (!) End of Life, nun aber mal schnell zu Python 3 wechseln. Keine Ahnung, warum man sich die ganzen tollen Features, die in den letzten 10+ Jahren hinzugekommen sind, freiwillig entgehen lässt...

    http://pythonclock.org/

    from tkinter import *

    Sternchenimports sind ganz schlecht, müllen den globalen Namensraum zu und führen oft zu unübersichtlichen Bugs. Weg damit, z.B. durch from tkinter import a, b, c ersetzen.

    import RPi.GPIO as GPIO
    import wiringpi as wiringpi

    Warum zwei verschiedene GPIO-Bibliotheken? Das ist eher suboptimal. Und am besten gleich das deutlich schönere, moderne, stetig weiterentwickelte gpiozero verwenden!

    file = open('/sys/devices/w1_bus_master1/w1_master_slaves')
    w1_slaves = file.readlines() # Read 1-wire slaves list
    file.close()

    Dateien öffnet man idealerweise mit einem Kontextmanager (with open(...) as f:), dann spart man sich das explizite Schließen und vergisst es nicht. In Python 3 noch einfacher mit pathlibs Path.read_text.

    file ist in Python 2 übrigens eine Builtin-Function die du hier mal eben überschreibst. Kann böse enden.

    Zaehler=Zaehler+1

    So etwas schreibt man schöner als variable += x. Variablennamen besser auf Englisch, ist halt beim Programmieren so.

    PEP 8, Quasi Gesetz in der Python-Community, missachtest du komplett. Das ist ungeschickt, weil jeder halbwegs erfahrene Python-Programmierer bei der Variable Zahl eine Klasse (keine Instanz!) erwartet...

    Das hat auf Modulebene nichts zu suchen, wie man eine Hauptfunktion erstellt und aufruft, siehst du in meinem obigen Code.

    Die while-Schleife am Ende brauchst du nicht. Aus der ebenfalls verlinkten Python-Doku:

    Zitat

    The entire Python program exits when no alive non-daemon threads are left.

  • Eigentlich habe ich es gemacht wie in diesem Video:

    Von Videotutorials halte ich absolut nichts, aus genau diesem Grund. Wie soll es ein Thema korrekter vermitteln als die offizielle Doku??? Das Problem ist, dass in dem Video (ja, ich habe etwas vor gespult :baeh2:) zwei Instanzen der selben Thread-Klasse erstellt werden und somit in beiden das Lock verwendet wird - bei dir ja nur in einem Thread. So funktioniert's eben nicht.

  • Hallo Linus,

    ich muß das morgen mal in Ruhe durcharbeiten. Wie unschwer zu erkennen ist,

    sind meine Kenntnisse sehr begrenzt.

    Ich hatte inzwischen das Programm weiter geschrumpft:

    Das wird jetzt nicht viel bringen, aber ich stells einfach mal rein. Die While Schleife (Zeile 22) sollte doch durchlaufen

    ohne das der andere Thread alle 10 Sekunden die Printausgabe macht?

    Wie gesagt, ich muß mich da in Ruhe reindenken.

    Vielen Dank!


    Gruß Reinhard

    • Offizieller Beitrag

    def t1() -> None:

    Teilweise OT: Ist das wirklich beabsichtigt? Muss man in einem Beispiel bewusst sinnlose Zeichenketten einfügen nur weil es geht? Wie ich grade gegoogled habe, sollen die

    ->

    zeigen was die Funktion zurückgibt - ist ja nicht so, dass es am Ende der Funktion auch stehen würde (oder eben nicht). Einen Vorteil sehe ich daran nicht. Es verkompliziert dein Beispiel und es auch eine generell ein schrottige Syntax und hat in Python nichts verloren. Aber hey, features der features wegen :shy:

  • Hm, wenn's dir nicht passt kannst du ja nächstes mal das Beispiel liefern. Ich versehe all meinen Python-Code mit Type-Annotations (insbesondere den Code, an dem ich nicht allein arbeite) - ich sehe keinen Grund, warum ich mir das bei einem Beispiel abgewöhnen sollte.

    Es verkompliziert dein Beispiel

    Korrekt.

    generell ein schrottige Syntax und hat in Python nichts verloren

    Agree to disagree. Rechtfertigen muss sich hier ja aber niemand.

  • Hallo,

    dbv: wenn man seinen Code mit einem statische Type Checker wie z.B. Mypy prüft, dann gehört auch da eine Type Annotation hin. Ob du das sinnlos findest oder nicht interessiert den Type Checker so rein gar nicht.

    Zum Thema:

    ReinhardT : dein Denkfehler ist noch, dass ein Lock auto-magisch anderen Threads von der Ausführung stoppt. Und das ist eben _nicht_ der Fall! Es funktioniert so: X Threads teilen sich die Instanz eines Lock-Objekts. Für jeden kritischen Bereich wird für den entsprechenden Codeanschnitt im Thread die `acquire` Methode aufgerufen. Versucht ein anderer Thread, während `acquire` aktiv ist, die `acquire` Methode aufzurufen, DANN wird die Ausführung des Codes des Threads an der Stelle unterbrochen, bis die `release` Methode der Instanz des Lock-Objekts aufgerufen wurde.

    Threading is generell in Python nicht so der Hit, dass sagen ja auch die Macher von Python. Außerdem laufen Threads zumindest in CPython _nicht_ parallel, weil das der GIL verhindert. Threads sind in CPython auch nur kooperatives Multitasking, keine echte Parallelität.

    Programme mit Threads sind generell nicht unbedingt einfach und wenn noch Locking dazu kommt, wird es nicht einfacher.

    Was hast du den vor, dass dich zu der Annahme verleitet, dass du Thread mit Locking brauchst? Die Frage ist noch offen.

    Gruß, noisefloor

  • Hallo,


    Zitat

    Was hast du den vor, dass dich zu der Annahme verleitet, dass du Thread mit Locking brauchst? Die Frage ist noch offen.

    Es geht darum, sie Zeit zu messen in der sich die Temperatur zB. um 5 Grad erhöht.

    Ich hatte naiverweise vor einfach eine Schleife mit time.sleep(1) laufen zu lassen

    und bei jedem Durchlauf die Temperatur zu messen.

    Die Anzahl der Durchläufe würde dann so ungefähr der Anzahl der Sekunden entsprechen.

    Hat aber nicht funktioniert, die wirklich verstrichene Zeit war viel höher.

    Da ich annahm, das der andere Thread Schuld war, wollte ich ihn in dieser Zeit stoppen.

    Die wirkliche Ursache der Zeitabweichung ist aber, das die Zeitmessung allein schon ca. 1 Sekunde

    dauert.

    Jetzt bilde ich einfach die Zeitdifferenz zwischen den Ereignissen.

    Gruß Reinhard

  • Hallo,

    ok - aber das erklärt immer noch nicht die Notwendigkeit eines Locks... - denn nach meinem Verständnis kann man das beschriebene problemlose in einem Thread machen. Ein Lock braucht man z.B. bei konkurrierenden Schreib-/Lese-Zugriffen auf Daten, um Race Conditions zu vermeiden.

    Wenn ein 2. Thread auf das Ergebnis des 1. warten muss, weil Thread 2 ein Ergebnis braucht, dann geht das ganz einfach mit einer FIFO Queue.

    Gruß, noisefloor

    • Offizieller Beitrag

    wenn man seinen Code mit einem statische Type Checker wie z.B. Mypy prüft, dann gehört auch da eine Type Annotation hin. Ob du das sinnlos findest oder nicht interessiert den Type Checker so rein gar nicht.

    Zitat

    Mypy is an optional static type checker for Python

    Optional - kann man also machen muss man nicht. Ich bin dafür Beispiele extrem einfach zu halten und abstruse Pfeile erhöhen weder die Lesbarkeit noch hat der User auch nur irgendeinen Mehrwert.

  • Hallo,

    Zitat

    Ich bin dafür Beispiele extrem einfach zu halten und abstruse Pfeile erhöhen weder die Lesbarkeit noch hat der User auch nur irgendeinen Mehrwert.

    Da hättest du dich vielleicht mal stärker bei der PEP484 und 526 einbringen müssen. Jetzt ist es zu spät. Und jetzt Leute verurteilen, die das Anwenden, nur weil mal es selber doof findet, ist auch keine Lösung.

    Gruß, noisefloor

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!