For-Loop + Returnvalue Funktion

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
BB90
User
Beiträge: 4
Registriert: Dienstag 18. Februar 2020, 19:46

Hallo zusammen,

mein Ziel ist es abhängig vom Userinput mit der For-Loop weiterzumachen.
Dazu hab ich 2 Möglichkeiten entweder mit user_input == 1 oder mit einer Timer.

Nur Funktioniert die Variante mit dem Timer nicht, da "log_timeout == True" nicht berücksichtigt wird.
Das Script bleibt bei der ersten Schleife bei dieser Möglichkeit einfach hängen.

Wäre superfroh bei einer Antwort!
Danke Jon


Code: Alles auswählen


#Code...

wait = 5
log_timeout = False
    
for x in range(5):
#Code...
    
    def timeout():
        log_timeout == True
        print("Timeout occured")
        return log_timeout

    t = Timer(wait, timeout)
    t.start()    
    user_input = int(input("Press 0 to stop and 1 to continue, otherwise we continue in a few seconds \n"))
    
    if user_input == 0:
       t.cancel()
       break
    elif user_input == 1 or log_timeout == True:
       print("We continue anyway")
       continue  
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@BB90: `log_timeout` wird da nie geändert. Das ``return log_timeout`` in der `timeout()`-Funktion macht keinen Sinn weil a) dieser Rückgabewert von niemandem entgegen genommen wird und b) das ja der gleiche wert (immer `False`) ist den `log_timeout` nun mal hat.

Der Vergleich mit dessen Ergebnis dann nichts gemacht wird ist offensichtlich sinnfrei. Wenn es kein Vergleich sondern eine Zuweisung wäre, wäre es auch sinnfrei, weil dann `log_timeout` in `timeout()` ein lokaler Name wäre der mit dem `log_timeout` ausserhalb der Funktion nichts zu tun hätte.

Man vergleicht keine Wahrheitswerte mit literalen Wahrheitswerten, denn da kommt doch eh nur wieder ein Wahrheitswert heraus, und zwar der den man bei ``== True`` doch sowieso schon hatte.

Das ``continue`` ist sinnfrei, und mal sollte diese Anweisung auch eher meiden.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Ich habe die Vermutung, dass @BB90 außerdem denkt, dass durch den Timer das Warten auf den Abschluss der Eingabe beendet werden kann. Das funktioniert mit Python-Bordmitteln soweit ich weiß nicht.
BB90
User
Beiträge: 4
Registriert: Dienstag 18. Februar 2020, 19:46

Gut, dann sag mir mal wie man den "sinnfreien" scheiß, "sinnvoller" machen kann.
Mehr kann ich als Anfänger der Programmierung aus deiner "sinnvollen" Antwort nicht gewinnen. Oder es deine Art wie man Programmierer zum Denken anregen möchte...

Anbei meine Gedanken....
Der Vergleich mit dessen Ergebnis dann nichts gemacht wird ist offensichtlich sinnfrei. Wenn es kein Vergleich sondern eine Zuweisung wäre, wäre es auch sinnfrei, weil dann `log_timeout` in `timeout()` ein lokaler Name wäre der mit dem `log_timeout` ausserhalb der Funktion nichts zu tun hätte.
Stimmt danke für den Hinweis, Der Vergleich ist falsch wird korrigiert in eine Zuweisung. Und um eben das Problem der lokalen Variable zu lösen, dachte ich mir gebe ich einen Returnwert aus, welcher außerhalb der Funktion wiederverwendet werden kann, was ist daran falsch?
Das ``continue`` ist sinnfrei, und mal sollte diese Anweisung auch eher meiden.
Ok, wie kann ich dem Script dann mitteilen, dass er die Schleife weiter abarbeiten soll?
Man vergleicht keine Wahrheitswerte mit literalen Wahrheitswerten, denn da kommt doch eh nur wieder ein Wahrheitswert heraus, und zwar der den man bei ``== True`` doch sowieso schon hatte.
Besser so?
elif user_input == 1 or log_timeout
Zuletzt geändert von BB90 am Dienstag 18. Februar 2020, 23:24, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es ist nicht so einfach wie du das denkst. Und je nach Betriebssystem wüsste ich gar nicht, wie ich es überhaupt lösen würde. Unter Windows zB. Unter Unix kannst du hingegen das zB hier machen: https://stackoverflow.com/questions/133 ... th-timeout

Oder du sagst den Leuten einfach, sie sollen Control-C drücken, wie bei jedem anderen Programm auch. Dann reicht das time.sleep.
BB90
User
Beiträge: 4
Registriert: Dienstag 18. Februar 2020, 19:46

@_deets_ das habe ich mir auch schon durchgelesen gehabt, ich verwende Windows.
Aber warum ist es nicht so einfach?

Im Grunde möchte ich folgendes:
Wenn die Zeit im Timer abgelaufen ist, dann soll das Elif zusätzlich als Auswertung über den Bool-Wert log_timeout möglich sein.
Wo genau liegt das Problem? Warum kann das log_timeout nicht im Elif berücksichtigt werden, wie kann ich es schaffen den Rückgabewert auch außerhalb der Funktion nutzbar zu machen?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Problem ist, dass du zwar einen Timer starten kannst. Und den auch stoppen, wenn der User eine Eingabe VORHER gemacht hat.

Aber nicht später. Die Eingabe blockiert leider endlos. Mir zumindest ist kein Weg bekannt das zu ändern unter Windows. Mit Unix kann man diverse Wege beschreiten. Somit bleibt die Frage also stehen, und der User muss am Ende sogar wenn alles vorbei ist trotzdem eine Taste drücken- weil die Eingabe immer noch steht.

Control-C hingegen wertet das Terminal Programm selbst aus, und killt deinen Prozess. Wie gewünscht.

Ich habe antworten zu dem Problem für powershell gefunden. Die funktioniert ggf anders. Aber nicht (oder nicht so) mit Python.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@BB90: Der Wert bei ``return`` wird an den Aufrufer der Funktion zurückgegeben. Der Aufrufer ist der `Timer` und der erwartet keinen Rückgabewert und macht deswegen damit nichts. Darum macht es keinen Sinn dort ``return`` mit einem Wert zu verwenden.

Beim ``continue`` brauchst Du gar nichts mitteilen. Das ``continue`` macht da ganz einfach nichts was nicht auch ohne das ``continue`` sowieso passieren würde.

Das was Du willst ist nicht so einfach weil das einfach nicht vorgesehen ist. Schon gar nicht plattformübergreifend. Auch auf nur einer Plattform hängt das davon ab in welcher Umgebung man das ausführt. Terminal, welches Terminal, IDE, …. `input()` liest einfach blockierend von `sys.stdin`. Und die Dateischnittstelle bietet nicht wirklich viel, das dafür aber auf so ziemlich jedem System und in jeder Umgebung. Wenn man mehr Kontrolle haben möchte muss man sich auf bestimmte Umgebungen mit dazu passenden Bibliotheken einschränken, oder eine GUI-Anwendung schreiben.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

@BB90: Du hast das noch nicht explizit gessagt (oder ich habe es überleden): Soll sas Programm automatisch nach x Zeit, die es auf rine Eingabe wartet, automatisch und ohne Interaktion fortfahren? Das geht mit input in dieser Form nichr. Und mir ist kein Weg benannt, wie es plattformübergreifen mit Python Bordmitteln tut.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Ich kenne auch nur Möglichkeiten wo nach der Eingabe geprüft wird ob die Zeit überschritten wurde.


Evtl. könntest du es hinbekommen, wenn du mit Hilfe von multithreading einfach nach einer bestimmten Zeit ein "Enter" eingibst, mit einem Modul mit dem du die Tastatur ansteuern kannst, aber ob das funktioniert und ob das eine gute Idee ist weiß ich nicht, war nur eine Idee von mir.

Hab mal bisschen probiert:

Code: Alles auswählen

from pynput.keyboard import Key, Controller
import time
import threading

keyboard = Controller()


def send_key(key, input_time):
    time.sleep(input_time)
    keyboard.press(key)
    keyboard.release(key)


while True:
    threading.Thread(target=send_key, args=(Key.enter, 5)).start()
    test = input("Gib bitte was ein, du hast 5 Sekunden Zeit und die Eingabe wird automatisch bestätigt: ")
    print(f"Du hast {test} eingebeben" if test != "" else "Du hast nichts eingegeben")
    break
BB90
User
Beiträge: 4
Registriert: Dienstag 18. Februar 2020, 19:46

Top, vielen Dank an alle für die Erklärungen und Lösungsvorschläge!
Ich werde es ohne Timer und nur mit Usereingabe programmieren.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Jankie hat geschrieben: Mittwoch 19. Februar 2020, 07:18 Evtl. könntest du es hinbekommen, wenn du mit Hilfe von multithreading einfach nach einer bestimmten Zeit ein "Enter" eingibst, mit einem Modul mit dem du die Tastatur ansteuern kannst, aber ob das funktioniert und ob das eine gute Idee ist weiß ich nicht, war nur eine Idee von mir.
Das funktioniert nur, wenn der User dann nicht gerade zufaellig den Fokus genau innerhalb des Timeouts umschaltet. Und damit ist es nicht zuverlaessig. Was IMHO schlimmer ist, als es gar nicht zu machen.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Ja das weiß ich, aber wenn man selbst der einzige Anwender der eigenen Programme ist, dann denke ich ist sowas ok.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du das weisst, warum weist du dann nicht auf dieses Verhalten hin? Vor allem, wenn du NICHT weisst, ob der Themenersteller dieses Wissen hat, und ob deine implizite Annahem, er wuerde das nur fuer sich benutzen, denn auch stimmt?
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Weil ich meinen Beitrag nicht mehr editieren konnte um das hinzuzufügen. Weiß nicht wie es hier im Forum mit Doppelposts gesehen wird. Und ich habe nicht angenommen dass der Threaderersteller seine Programme nur für sich nutzt, ich habe da von mir gesprochen. Eventuell hab ich auch ein gewisses Grundwissen vorrausgesetzt, dass Tastatureingaben natürlich nur da landen wo auch der Fokus ist.
Antworten