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
Zeitlich Begrentzte Eingabe
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")
@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?
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?
- __blackjack__
- User
- Beiträge: 13007
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Boggel: Windows ist halt kein *nix.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
- __blackjack__
- User
- Beiträge: 13007
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
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.
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.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
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.
während `select` unter *nix wartet, bis eine ganze Zeile eingegeben wurde, wartet WaitForSingleObject nur auf den ersten Tastendruck.
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.
Code: Alles auswählen
import win32api
import win32event
stdin = win32api.GetStdHandle(-10)
if win32event.WaitForSingleObject(stdin, 1000):
print("Timeout")
else:
print("Taste gedrückt")
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.
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()
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
- __blackjack__
- User
- Beiträge: 13007
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
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.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
- noisefloor
- User
- Beiträge: 3843
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
hab's heute morgen mal unter Win ausprobiert, rein Interesse halber. Der folgende Code funktioniert:
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
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)
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