Seite 1 von 1

while mit tastendruck abbrechen

Verfasst: Freitag 26. Juni 2009, 13:48
von draufunddran
Hallo leute,

bin sehr neu im Bereich Python, und hab mal ein für sicherlich einfache frage.

Ich habe eine "While-Schleife" und würde die gerne so lange laufen lassen bis eine bestimmte Taste gedrück wurde.

mit raw_input geht es ja nicht, da er ja dann so lange wartet bis er eine Eingabe hat oder?

greetz draufunddran

Verfasst: Freitag 26. Juni 2009, 14:46
von limepix
auf windows systemen kannst du n programm mit Ctrl-C abbrechen. um den fall abzufangen könntest du das folgendermaßen machen:

Code: Alles auswählen

try:
    while 1:
        print '.'
except KeyboardInterrupt:
    print 'Stop'
greetz ;)

Verfasst: Freitag 26. Juni 2009, 14:50
von HerrHagen
Wenn du Windows nutzt, wäre das Modul msvcrtvielleicht etwas für dich.

Verfasst: Freitag 26. Juni 2009, 20:14
von Defnull
limepix hat geschrieben:auf windows systemen kannst du n programm mit Ctrl-C abbrechen.
Das geht auch auf Nicht-Windows Systemen.

Verfasst: Freitag 26. Juni 2009, 20:24
von derdon
limepix sagt trotzdem die Wahrheit :wink: Um on-topic zu bleiben: für UNIX-ähnliche Betriebssysteme gibts noch curses.

Verfasst: Freitag 26. Juni 2009, 21:02
von problembär
Ich glaube, curses macht in der Linux-Konsole so ein Fenster auf, das man nicht haben will.

Für ungeblockte Tastenabfragen in der Linux-Konsole gab's stattdessen mal den KeyHandler.

Für Python-Anfänger aber wohl etwas schwer zu benutzen :roll:.

Gruß

Verfasst: Freitag 26. Juni 2009, 21:21
von lunar
Weder ein Anfänger noch sonst irgendjemand sollte diesen Code verwenden. Er ist unschön und unnötig komplex, und noch dazu fehlerbehaftet. Das geht kürzer, eleganter und allgemein besser.

Verfasst: Samstag 27. Juni 2009, 08:54
von mkesper
Wieso gibt's da keine betriebssystemunabhängige Implementierung in Python?

Verfasst: Samstag 27. Juni 2009, 09:11
von darktrym
Zum einen wäre die einzig halbwegs plattformunabhängige Variante über curses, wobei Python für Windows dies nicht in der Standardinstallation einem zur Verfügung stellt. Zum anderen bin ich mir auch nicht sicher, ob es eine solche Funktion in curses gibt.

Eventuell könnte man das nachbauen mit einen Thread und curses.getch() oder über eine grafische Anwendung(mit GUI).

Verfasst: Samstag 27. Juni 2009, 10:18
von lunar
mkallas hat geschrieben:Wieso gibt's da keine betriebssystemunabhängige Implementierung in Python?
Die Antwort ist einfach: Niemand hat das so sehr gebraucht, um sich für eine Aufnahme in die Standardbibliothek einzusetzen.

@darktrym
Das lässt sich schon plattformunabhängig implementieren. Die Lösung über "termios" sollte unter jedem modernen Unix-Derivat laufen, für Windows enthält die Standardbibliothek bereits eine entsprechende Funktion.

Verfasst: Samstag 27. Juni 2009, 22:31
von problembär
lunar hat geschrieben:Das geht kürzer, eleganter und allgemein besser.
Nur schade, daß da für das Einlesen jedes einzelnen Zeichens die Terminal-Einstellungen umgestellt werden.

(Außerdem beruht die dort genannte Funktion ebenfalls auf dem dort weiter oben gezeigten KeyHandler-Code.)

Gruß

Verfasst: Sonntag 28. Juni 2009, 12:01
von lunar
Ich denke nicht, dass es ein Problem darstellt, wenn die Terminaleinstellungen jedes Mal geändert werden. Selbst auf alten Systemen sollte das keine für den Nutzer spürbaren Verzögerungen nach sich ziehen. Falls das der Fall ist, kann man dieses Problem relativ trivial lösen.

Durch die Verwendung der with-Anweisung ist garantiert, dass das Terminal unter allen Umständen wieder in den Ausgangszustand versetzt wird. Das ist bei keiner deiner Varianten der Fall. Die erste setzt das Terminal im Falle einer Ausnahme gar nicht zurück. Die zweite Variante versucht, dazu den Destruktor zu nutzen, obwohl Python nicht garantiert, dass dieser unter allen Umständen aufgerufen wird. Außerdem garantiert Python die Existenz globaler Namen zu diesem Zeitpunkt nicht mehr, so was diesen unschönen lokalen Import erforderlich macht. In der zweiten Variante wird zudem eine Methode aufgerufen, die gar nicht definiert ist.

Ich denke übrigens nicht, dass jerchs Funktion auf deinem Code basiert. Die einzige Gemeinsamkeit ist der eh unvermeidliche Aufruf von "tcsetattr()" und "tcgetattr()" zum Speichern und Wiederherstellen des Status. Ansonsten ist so ziemlich alles anders, so nutzt er "ttc.setcbreak()", wo du die Terminaleinstellungen manuell manipulierst. Außerdem verzichtet die Funktion auf den nicht portablen Aufruf von "fcntl()" (dessen Sinn ich in deinem Code eh nicht ganz verstehe).

Verfasst: Sonntag 28. Juni 2009, 20:36
von jerch
Naja für non-blocking read wäre eine fcntl-Manipulation unter älterer Python-Version durchaus interessant. Die getch-Funktion des curses-Modul unterstützt das meines Wissens nach, ich hatte da bewußt drauf verzichtet.

@problembär:
Ich hab Deine Version nicht mehr parat (und den Link nicht verfolgt :oops:), mir war da damals aber zuviel magic drin, unklare und unsinnige Strukturierung mit Klassenentwurf, Zustands-Inkonsistenzen etc.
Kurzum ich würde den Code so nicht weiterempfehlen. Ist nicht persönlich gemeint, nur kann jmd., der relativ neu in der Sprache ist, so etwas gar nicht abschätzen und läuft Gefahr, mit fehlerhaftem Code zu arbeiten.

Eine vereinheitlichende Modul-Implementation für die gängigen Plattformen ist ziemlich einfach machbar, mit kbhit-Funktionalität, non-blocking und Unicode-Unterstützung wirds etwas komplexer. Falls Interesse besteht, schiebe ich die gern nach...

BTW, um die curses-Unterstützung in Python ist es auch nicht so gut bestellt (Zukunft des Moduls?), vllt. sollte man daran was machen.

Grüße jerch

Verfasst: Sonntag 28. Juni 2009, 22:40
von problembär
Ok, ich wußte die Terminal-Einstellungen auch nicht aus dem Kopf, das heißt, ich hab' die paar Zeilen Code ja auch aus irgendwelchen Tutorials und Postings zusammengeschraubt. Ist eigentlich egal, wo das nun herkam, es ist jedenfalls, wie man's macht, die Module lassen ja auch kaum was anderes zu.

Mal angenommen, man wollte die Terminal-Einstellungen nur einmal setzen, dann eine gewisse Zeit ungeblockt einlesen, und am Ende wieder zurückstellen.
Ist es da so abwegig, eine Funktion "setTerminalToUnblockedReading()" und eine Funktion "setTerminalBack()" zu machen, und wenn man dann schon zwei Funktionen hat, die in einer Klasse zusammenzufassen? Liegt doch irgendwie nahe ...

Gruß

Verfasst: Montag 29. Juni 2009, 00:10
von jerch
Auf die Designschwächen Deines Klassenansatzes ist ja nun schon mehrfach hingewiesen worden. Was soll das sys.exit da drinnen? Hast Du Dir über die Seiteneffekte/Terminalzustand mal Gedanken gemacht? (Das __del__ macht es eigentlich nur noch schlimmer.)
Deine Klasse ist nichts weiter als eine Ansammlung von Funktionen und Terminalsettings. Dann setzt Du den raw-Modus im Konstruktor der Klasse. Was passiert jetzt wohl bei multiplen Importen und Instantiierungen (hässliches denglish) in verschiedenen Modulen?
Auf all diese Dinge haben lunar und str1442 schon hingewiesen.

Fummeleien an so lebenswichtigen Ressourcen wie stdin/stdout sollten sich auf ein Minimum beschränken bzw. so schnell wie mgl. den Ausgangszustand restaurieren. Oder aber mit klarer API wie bei curses (initscr()) die Verantwortung an den Nutzer durchreichen, in der Hoffnung, das dieser damit umzugehen weiß. Magic wie - oh jetzt hab ich KeyHandler() aufgerufen, warum geht das Terminal bloß nicht mehr - sind in meinen Augen ein Designfehler.

Verfasst: Montag 29. Juni 2009, 00:20
von lunar
problembär hat geschrieben:Ist es da so abwegig, eine Funktion "setTerminalToUnblockedReading()" und eine Funktion "setTerminalBack()" zu machen, und wenn man dann schon zwei Funktionen hat, die in einer Klasse zusammenzufassen? Liegt doch irgendwie nahe ...
Klassen verbinden Daten und zugehöriges Verhalten und sind nicht bloß Namensräume für Funktionen.

Verfasst: Montag 29. Juni 2009, 10:28
von EyDu
lunar hat geschrieben:Durch die Verwendung der with-Anweisung ist garantiert, dass das Terminal unter allen Umständen wieder in den Ausgangszustand versetzt wird.
Es kann durchaus mal wichtig sein: "__exit__" wird nicht in jedem Fall aufgerufen. *POWER OFF*.

Verfasst: Montag 29. Juni 2009, 11:18
von lunar
Dann ist der Zustand des Terminals dein geringstes Problem ;)