Seite 1 von 1
Zeitlich Begrentzte Eingabe
Verfasst: Dienstag 18. Dezember 2018, 20:57
von Boggel
Hallo,
ich bin neu in diesem Forum und in der Sprache Python.
Ich wollte ein kleines Programm schreiben in dem man ein zeitlich bregrenzte Eingabe hat.
Also einen input der z.B. nach 5 Sekunden abricht und dann das Programm weitermacht.
Ist dies möglich? Wenn ja bitte ich um Antwort.
Mfg Nils
Re: Zeitlich Begrentzte Eingabe
Verfasst: Dienstag 18. Dezember 2018, 21:32
von snafu
Wo willst du das denn machen? Auf der Kommandozeile oder als grafisches Programm?
Re: Zeitlich Begrentzte Eingabe
Verfasst: Dienstag 18. Dezember 2018, 22:00
von Boggel
Auf der Kommandozeile.
Re: Zeitlich Begrentzte Eingabe
Verfasst: Mittwoch 19. Dezember 2018, 09:08
von Sirius3
Das hängt vom System ab, auf dem das laufen soll. Unter *nix einfach per `select`:
Code: Alles auswählen
import sys
import select
print("Du hast 5s Zeit, die Antwort zu geben:")
if select.select([sys.stdin],[],[], 5)[0]:
value = input()
else:
print("Zu spät")
Re: Zeitlich Begrentzte Eingabe
Verfasst: Mittwoch 19. Dezember 2018, 15:02
von Boggel
@Sirius3
Ich speichere das immer unter dem File .py ab um es dann unter windows 10 in der Kommandozeile zu starten.
Dein Vorschlag mit dem Code hat leider nicht funktioniert.
Die Fehlermeldung lautet: OSError: [WinError 10093] Die Anwendung hat die Funktion WSAStartup nicht aufgerufen, oder bei dieser Funktion ist ein Fehler aufgetreten
Kannst du mir da weiterhelfen?
Re: Zeitlich Begrentzte Eingabe
Verfasst: Mittwoch 19. Dezember 2018, 15:06
von __blackjack__
@Boggel: Windows ist halt kein *nix.

Re: Zeitlich Begrentzte Eingabe
Verfasst: Donnerstag 20. Dezember 2018, 13:53
von Boggel
@_blackjack_
In unserer Familie gibt es zwar noch einen C64 aber was hilft mir das bei meiner Python Programmierung.
Ich will ja eben wissen wie ich die Zeitlich begrentzte EIngabe unter Python programmieren kann.
Re: Zeitlich Begrentzte Eingabe
Verfasst: Donnerstag 20. Dezember 2018, 14:05
von __blackjack__
Du willst wissen wie Du eine zeitlich begrenzte Eingabe unter Python *unter Windows* programmieren kannst. Das läuft dann aber nicht unter *nix-Systemen. So wie die Lösung von Sirius3 für *nix-Systeme eben nicht für Windows-Systeme funktioniert.
Falls es für Dein Problem keine plattformübergreifende Lösung in Form einer fertigen Bibliothek gibt, würde ich das ja ganz sein lassen. Als GUI-Programm ginge es plattformübergreifend. Bei Tkinter würde man zum Beispiel mit der `after()`-Methode einfach eine Rückruffunktion/-methode registrieren, die nach der definierten Zeit das Eingabefeld und gegebenfalls die Schaltfläche zur Bestätigung der Eingabe deaktiviert.
Re: Zeitlich Begrentzte Eingabe
Verfasst: Donnerstag 20. Dezember 2018, 14:32
von __deets__
Noch als Ergaenzung: Windows macht einem die Arbeit mit der Konsole nicht so einfach. Darum hat Python die notwendigen Mittel nicht an Bord, um dein Problem zu loesen. Was du brauchst ist "WaitForSingleObject" oder "WaitForMultipleObjects". AFAIK kommst du an die nur entweder mit Dritt-Modulen, oder per ctypes und selbst gewrappter win32-API. Und fuer keines von beiden habe ich fertige Beispiele gefunden.
Re: Zeitlich Begrentzte Eingabe
Verfasst: Donnerstag 20. Dezember 2018, 14:54
von Sirius3
während `select` unter *nix wartet, bis eine ganze Zeile eingegeben wurde, wartet WaitForSingleObject nur auf den ersten Tastendruck.
Code: Alles auswählen
import win32api
import win32event
stdin = win32api.GetStdHandle(-10)
if win32event.WaitForSingleObject(stdin, 1000):
print("Timeout")
else:
print("Taste gedrückt")
wenn man also in einer bestimmten Zeit eine ganze Zeile eingegeben haben will, muß man das selbst noch über eine Zeitmessung machen, also auf einen Tastendruck warten, über ReadConsole ein einzelnes Zeichen lesen, Timeout-Zeit entsprechend anpassen und wieder warten.
Re: Zeitlich Begrentzte Eingabe
Verfasst: Donnerstag 20. Dezember 2018, 19:23
von ThomasL
Ich dachte mir, da könnte man doch auch was mit pygame machen.
Der feine win32api Code ist natürlich eleganter.
Aber es gibt wie immer viele Wege, die zum Ziel führen.
Code: Alles auswählen
#!/usr/bin/env python3
import os
from pygame.locals import *
from time import time
from pygame import init, display, event, quit
def main():
os.environ['SDL_VIDEO_CENTERED'] = '1'
init()
display.set_caption('Innerhalb 5 Sekunden Text eingeben!')
display.set_mode((400, 1))
times_up = False
pressed_keys = []
start_time = time()
while not times_up:
for my_event in event.get():
if my_event.type == KEYDOWN:
pressed_keys.append(my_event.key)
if my_event.key == K_ESCAPE:
pass
if my_event.key == K_UP or event.key == K_w:
pass
if my_event.key == K_p:
pass
times_up = (time() - start_time) > 5.0
quit()
print(''.join([chr(key) for key in pressed_keys]))
if __name__ == '__main__':
main()
Re: Zeitlich Begrentzte Eingabe
Verfasst: Donnerstag 20. Dezember 2018, 19:54
von __blackjack__
Da sieht man den Text ja gar nicht. Und man muss auch beachten das hier alle möglichen Tasten ausser Buchstaben gedrückt werden können, die erfasst werden. Also da ist eine kleine GUI dann doch praktischer und weniger Aufwand. Tk ist Teil der Standardbibliothek, und man bekommt die Bearbeitung eines Eingabefeldes quasi umsonst, was man sich mit Pygame alles noch selbst programmieren müsste.
Re: Zeitlich Begrentzte Eingabe
Verfasst: Donnerstag 20. Dezember 2018, 21:53
von noisefloor
Hallo,
hab's heute morgen mal unter Win ausprobiert, rein Interesse halber. Der folgende Code funktioniert:
Code: Alles auswählen
import msvcrt
import time
import sys
#Quelle: https://stackoverflow.com/questions/15528939/python-3-timed-input
class TimeoutExpired(Exception):
pass
def eingabe_mit_timeout(prompt, timeout, timer=time.monotonic):
sys.stdout.write(prompt)
sys.stdout.flush()
endzeit = timer() + timeout
eingabe = []
while timer() < endzeit:
if msvcrt.kbhit():
eingabe.append(msvcrt.getwche())
if eingabe[-1] == '\r':
return ''.join(eingabe[:-1])
time.sleep(0.04)
raise TimeoutExpired
ereignisse = (('Wann endete der 30-jährige Krieg?', 1648),
('In welchem Jahr begann die französische Revolution?', 1789),
('Im welchem Jahr wurde Helmut Kohl Bundeskanzler?', 1982))
print('5 Sekunden pro Antwort')
time.sleep(1)
for zaehler, ereignis in enumerate(ereignisse, 1):
print('{}. Frage'.format(zaehler))
time.sleep(1)
try:
prompt = '{}\r\n'.format(ereignis[0])
antwort = eingabe_mit_timeout(prompt, 5)
except TimeoutExpired:
print('Zu langsam...')
print('Die Antwort wäre {} gewesen.'.format(ereignis[1]))
else:
if int(antwort) == ereignis[1]:
print('Richtig!')
else:
print('Die Antwort ist leider falsch. Richtig ist: {}'.format(ereignis[1]))
time.sleep(1)
Die Quelle, wo der Kern der Lösung herkommt, ist im Kommentar im Code vermerkt. Das Spielchen habe ich testweise drum rum gebaut, um das zu auszuprobieren.
Es gibt im Netz noch eine 2. Weg, das unter Win (bzw. Cross-Plattform) zu machen, mittels `threading.timer`. Wobei ich die Lösung mittels `select` bzw die obige für Win besser finde.
Gruß, noisefloor
Re: Zeitlich Begrentzte Eingabe
Verfasst: Freitag 21. Dezember 2018, 11:57
von Boggel
@noiseflorr
Danke der Code hat geklappt.
Hab ihn für mich abgeändert funktioniert alles.
Mfg Nils