time.sleep alternative

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
Daniel Schreiber
User
Beiträge: 21
Registriert: Sonntag 14. Januar 2018, 15:03

Hallo, ich habe ein programm, in welchem in einer while schleife ein bild für ein paar sekunden erscheinen soll, während, sobald ich eine taste drücke die jetztige zeit gemessen werden soll. Dafür benutze ich die time.sleep methode. Mein Problem ist allerdings, dass während das bild angezeigt wird, also time.sleep aktiv ist, keine zeit gemessen wird, weil alles schläft, nicht nur das bild. Kennt jemand eine Alternative, um einen delay einzubauen, der nicht global ist, sondern nur bei bestimmten objekten? oder eine möglichkeit, ein bild für nur ein paar sekunden anzuzeigen ?

Ich hoffe, jemand kann mir helfen und bin sehr dankbar für jegliche Vorschläge.
Sirius3
User
Beiträge: 18267
Registriert: Sonntag 21. Oktober 2012, 17:20

Welches Rahmenwerk benutzt Du denn zum Anzeigen?
codemode89
User
Beiträge: 12
Registriert: Mittwoch 26. September 2018, 17:39

Ohne Code schwer zu sagen.
Aber wenn der Thread schläft läuft die Zeit im Universum weiter :P und ist über print (datetime.datetime.now()) abzurufen.
Endzeit-Startzeit = vergangene Zeit.

Code: Alles auswählen

import time
import datetime
start_time = datetime.datetime.now()
time.sleep(5)
end_time = datetime.datetime.now()

print("elapsed time: " + str((end_time-start_time)))
Wobei ich denke das time.sleep hier wohl überhaupt nicht gebraucht wird, aber das ist nur eine Vermutung da kein Code vorhanden ist.

Oder ich habe das Problem falsch verstanden

Hier nochmal eine andere delay Methode

Code: Alles auswählen

import datetime

def delay(duration_in_seconds):
    current_time = datetime.datetime.now()
    end_time = current_time + datetime.timedelta(0,duration_in_seconds)
    while current_time<end_time:
        current_time = datetime.datetime.now()


print("start: " + str(datetime.datetime.now()))
delay(5)
print("end: " + str(datetime.datetime.now()))
Daniel Schreiber
User
Beiträge: 21
Registriert: Sonntag 14. Januar 2018, 15:03

Hallo, ich benutze einen Turtle, der als shape ein entsprechendes Bild hat
Daniel Schreiber
User
Beiträge: 21
Registriert: Sonntag 14. Januar 2018, 15:03

Vielen Dank für deine Vorschläge, der code sieht so aus. Es ist so, dass wenn ich am ende die Reaktionszeit anzeigen lassen will, eine Liste erscheint, die exakt die zeitverzögerung enthält, die dem wert von time.sleep entspricht. Das ist natürlich falsch, sie soll ja die differenz zwischen anzeigezeit und drückzeit enthalten. Vielen Dank für alle Antworten

Code: Alles auswählen

f = turtle.Screen()
f.bgcolor("black")
f.title("Reaktionszeittest")

bilder = ["dome.gif","annegret.gif","marcel.gif","andreas.gif","regrecht.gif"]
bild = turtle.Turtle()
bild.hideturtle()

for bild in bilder:
    f.register_shape(bild)

zeiten_true = list([])
zeiten_false = list([])
zeiten_dif = list([])

def zeitmessen():
    zeiten_false.append(time.time())

f.listen()
turtle.onkey(zeitmessen,"space")

w = True
while w == True:
    bild = turtle.Turtle()
    bild.hideturtle()
    f.update()
    if len(zeiten_true) != 3:
        time.sleep(3)
        bild.shape(random.choice(bilder))
        bild.showturtle()
        time.sleep(0.85)
        bild.hideturtle()
        time.sleep(random.randint(2,7))
        zeiten_true.append(time.time())
    elif len(zeiten_true) == 3:
        for i in range(len(zeiten_true)):
            zeiten_dif.append(int(zeiten_true[i]) - int(zeiten_false[i]))
        print(zeiten_true)
        w = False
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich blicke da nicht durch. Aber wenn du statt Zeitpunkten Abstände haben willst, dann subtrahier doch deine Zeitpunkte in der Liste voneinander. Oder Merk dir den letzten Zeitpunkt, subtrahier “jetzt”, und setzte jetzt als neue letzten Zeitpunkt.
Benutzeravatar
__blackjack__
User
Beiträge: 14033
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Daniel Schreiber: Bei dem Code fehlen Importe.

`f` ist eine komische Abkürzung für `Screen`. Einbuchstabige Namen sind selten eine gute Idee. Ein Name soll dem Leser vermitteln was der Wert im Programm bedeutet, und nicht zum rätselraten zwingen.

An einen Namen sollten im gleichen Gültigkeitsbereich nur Objekte vom gleichen (Duck) Typ gebunden werden. Das `bild` mal für ein `Turtle`-Objekt und mal für Dateinamen verwendet wird, ist ein wenig verwirrend. Die erste für diesen Namen erstellte Schildkröte wird auch gar nicht verwendet. Das in der ``while``-Schleife immer neue Schildkröten erzeugt und am Ende ”versteckt” werden, ist auch nicht sinnvoll. Da würde man vor der Schleife *eine* erstellen und die bei Bedarf zeigen und verstecken und die Form, also das angezeigte Bild ändern.

``list([])`` ist ein komisches Konstrukt. Entweder ``list()`` *oder* ``[]``, aber beides kombiniert macht wenig Sinn.

Bei dem ``if``/``elif`` in der ``while``-Schleife ist die ``elif``-Bedingung genau dann wahr wenn die ``if``-Bedingung nicht mehr wahr ist. dafür gibt es ``else``. Wobei die ``while``-Schleife selbst aber schon zu umständlich ist mit dem `w`-Flag und dem Prüfen der Listenlänge. Du willst die Schleife genau 3× durchlaufen, das macht man mit einer ``for``-Schleife.

Code wie ``for i in range(len(zeiten_true)):`` ist in Python ein „anti pattern“. Man kann über Elemente von Sequenzen *direkt* iterieren, ohne den Umweg über einen Laufindex. Wenn man über ”parallele” Sequenzen iterieren möchte gibt es die `zip()`-Funktion.

Da hier eine leere Liste mit Werten befüllt werden soll, bietet sich zudem die „list comprehension“-Syntax an.

Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Funktionen (und Methoden) sollten alles was sie ausser Konstanten benötigen als Argumente übergeben bekommen.

Zwischenstand wäre dann ungefähr das hier:

Code: Alles auswählen

#!/usr/bin/env python3
import random
import time
import turtle
from functools import partial


def zeitmessen(zeiten_false):
    zeiten_false.append(time.time())


def main():
    screen = turtle.Screen()
    screen.bgcolor('black')
    screen.title('Reaktionszeittest')

    bild_dateinamen = [
        'dome.gif', 'annegret.gif', 'marcel.gif', 'andreas.gif', 'regrecht.gif'
    ]
    for dateiname in bild_dateinamen:
        screen.register_shape(dateiname)

    zeiten_true = list()
    zeiten_false = list()

    screen.listen()
    turtle.onkey(partial(zeitmessen, zeiten_false), 'space')

    bild = turtle.Turtle()
    bild.hideturtle()
    for _ in range(3):
        time.sleep(3)
        bild.shape(random.choice(bild_dateinamen))
        bild.showturtle()
        time.sleep(0.85)
        bild.hideturtle()
        time.sleep(random.randint(2, 7))
        zeiten_true.append(time.time())

    zeiten_diff = [
        int(zeit_true) - int(zeit_false)
        for zeit_true, zeit_false in zip(zeiten_true, zeiten_false)
    ]
    print(zeiten_true)


if __name__ == '__main__':
    main()
Das Problem bei `time.sleep()` ist, das die GUI-Hauptschleife dann nicht läuft und damit auch nicht auf den Tastendruck reagieren kann. Du musst dafür `turtle.mainloop()` aufrufen. Was aber bedeutet das Du Deine ``while``-Schleife nicht gleichzeitig laufen lassen kannst, was wiederum bedeutet, das Du das über `turtle.ontimer()` lösen musst, was wiederum bedeutet, das man das sauber nur über objektorientierte Programmierung lösen kann.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Daniel Schreiber
User
Beiträge: 21
Registriert: Sonntag 14. Januar 2018, 15:03

Wow, echt nett von dir, das so ausführlich zu betrachten. Warum braucht es am Ende "if __name__ == '__main__': main()", anstatt einfach "main()" aufzurufen?
Benutzeravatar
__blackjack__
User
Beiträge: 14033
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Daniel Schreiber: Weil das dann auch aufgerufen wird wenn `__name__` nicht den Wert '__main__' hat. Also auch dann wenn man das Modul einfach nur importiert, statt es als Programm auszuführen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten