Pausieren und Fortsetzen von Threads

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
kataba
User
Beiträge: 4
Registriert: Sonntag 17. Januar 2021, 23:15

Hallo ihr Lieben,

ich habe ein kleines Problem. Ich schreibe gerade an einem Programm, welches immer wenn das Wort 'Stopp' gesagt wird, unterbrochen werden soll, um nachzufragen ob der 'Stopp' tatsächlich gewünscht ist. Ist der Stopp nicht gewünscht, soll das Programm an der Stelle fortgesetzt werden, an der es gerade ist. Ist der Stopp erwünscht, soll das Programm dementsprechend abgebrochen werden.
Das ganze habe ich versucht über Threads zu lösen. Bisher bekomme ich es hin, dass Programm bei dem Wort 'Stopp' abzubrechen. Nun fehlt mir noch die Komponente, dass das Programm weiterläuft, wenn der Stopp nicht erwünscht ist. Wie könnte ich das ganze am besten für meinen Code realisieren?
Von Lock habe ich bereits gelesen. Werde daraus aber nicht wirklich schlau. Ich hoffe mir kann jemand helfen.

Hier mal mein Code bisher. Bei der Spracherkennung fehlt noch die init-Methode, ist aber für meine Frage nicht weiter relevant, also hab ich es so gelassen. Das eigentliche Programm habe ich übergangsweise durch das printen einer 1 ersetzt.

Code: Alles auswählen

import time
import threading
import speech_recognition as sr

class Spracherkennung():
    def _tester():
        r = sr.Recognizer()
        mic = sr.Microphone()
        #timeout=10
        with mic as source:
            r.adjust_for_ambient_noise(source)
            try:
                audio = r.listen(source)
            except sr.WaitTimeoutError:
                stt='NichtsErkannt'
                return stt
            
        try:
            stt = r.recognize_google(audio, language='de-DE').strip()
            print(stt)
            return stt
        except sr.UnknownValueError:
            stt='Fehler'
            print(stt)
            return stt
        except sr.RequestError:
            stt='Fehler'
            print(stt)
            return stt
          
class P(threading.Thread):

    def __init__(self, stop, hauptprogramm):
        threading.Thread.__init__(self)

        self.stop=stop
        self.hauptprogramm=hauptprogramm
        self.lock=lock


    def run(self):
        while True:
            if self.stop.isSet():
              print("Programmstopp wurde eingeleitet.")
              self.hauptprogramm.set()
              break
            else:
            	i=1
                print(i)
                time.sleep(1)



class PAbbruch(threading.Thread):

    def __init__(self,stop):
        threading.Thread.__init__(self)
        self.stop=stop

    def run(self):
      while True:
          Usereingabe=Spracherkennung._tester()
          if Usereingabe=="Stopp":
              break
      self.stop.set()
      print("Stopp wurde erkannt.")

if __name__=="__main__":

  hauptprogramm = threading.Event()
  stop=threading.Event()
  lock=threading.Lock()
  
  t1=P(stop,hauptprogramm)
  t2=PAbbruch(stop)
        
  t1.start()
  t2.start()

  hauptprogramm.wait()

  print("Das Progamm wurde beendet.")

kataba
User
Beiträge: 4
Registriert: Sonntag 17. Januar 2021, 23:15

Problem gelöst. :)
Brauche keine Antworten mehr, bekomme den Beitrag nur nicht gelöscht :)
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kataba: Eingerückt wird in Python mit vier Leerzeichen pro Ebene.

Das was im ``if __name__ == …``-Zweig steht gehört in eine Funktion. Dann passiert es nicht das ausversehen globale Variablen entstehen. `lock` wird in `P.__init__()` nämlich einfach so aus dem Nichts genommen. Wobei das auch nirgends benutzt wird — warum existiert das dann?

Keine kryptischen Abkürzungen in Namen oder gar Namen die ausschliesslich aus einer kryptischen Abkürzung oder gar nur einem einzigen Buchstaben bestehen.

Die beiden Klassen `P` und `PAbbruch` sind nicht wirklich Klassen sondern kompliziert geschriebene Funktionen. Man muss nicht von `Thread` erben um damit eine Funktion asynchron auszuführen.

Und auch `Spracherkennung` ist keine Klasse. Da ist es sogar noch schlimmer weil das nicht einfach nur umständlich ist, sondern extrem verwirrend eine ”Klasse” zu haben von der nie ein Exemplar erzeugt wird, weil da einfach nur eine Funktion drin steckt, die zudem auch noch als Implementierungdetail gekennzeichnet ist, die man von aussen also eigentlich gar nicht aufrufen dürfte. Was soll das denn?

Der zweite Thread ist unnötig weil damit ja dann *drei* Laufen wovon einer ausschliesslich damit beschäftigt ist auf das `hauptprogramm`-Event zu warten. Das ist Verschwendung. Das Hauptprogramm kann einfach im Hauptthread laufen. Womit das `hauptprogramm`-Event hinfällig wird. Das wäre selbst bei drei Threads unnötig, weil man stattdessen einfach per `join()` auf den Thread hätte warten können in dem das gesetzt wird.

Wenn man in zwei ``except``-Zweigen genau das gleiche macht, dann behandelt man das in *einem* ``except`` und kopiert den Code nicht.

Die beiden ``while True``-Schleifen haben gleich ein ``if`` mit einer Bedingung welche die Schleife abbricht — dann ist das doch die Bedingung die eigentlich negiert ins ``while`` gehört.

Die nicht den Namenskonventionen entsprechenden Namen aus dem `threading`-Modul sollte man nicht mehr verwenden.

Dein Code würde dann so aussehen (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import time
from threading import Event, Thread

import speech_recognition as sr


def listen_for_word():
    recognizer = sr.Recognizer()
    with sr.Microphone() as microphone:
        recognizer.adjust_for_ambient_noise(microphone)
        try:
            audio = recognizer.listen(microphone)
        except sr.WaitTimeoutError:
            return "NichtsErkannt"

    try:
        text = recognizer.recognize_google(audio, language="de-DE").strip()
    except (sr.RequestError, sr.UnknownValueError):
        text = "Fehler"

    print(text)
    return text


def wait_for_stop_command(stop):
    while listen_for_word() != "Stopp":
        pass
    stop.set()
    print("Stopp wurde erkannt.")


def do_something(stop):
    while not stop.is_set():
        print(1)
        time.sleep(1)

    print("Programmstopp wurde eingeleitet.")


def main():
    stop = Event()
    Thread(target=wait_for_stop_command, args=[stop], daemon=True).start()
    do_something(stop)
    print("Das Progamm wurde beendet.")


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten