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
while mit tastendruck abbrechen
auf windows systemen kannst du n programm mit Ctrl-C abbrechen. um den fall abzufangen könntest du das folgendermaßen machen:
greetz
Code: Alles auswählen
try:
while 1:
print '.'
except KeyboardInterrupt:
print 'Stop'
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 .
Gruß
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 .
Gruß
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.
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).
Eventuell könnte man das nachbauen mit einen Thread und curses.getch() oder über eine grafische Anwendung(mit GUI).
Die Antwort ist einfach: Niemand hat das so sehr gebraucht, um sich für eine Aufnahme in die Standardbibliothek einzusetzen.mkallas hat geschrieben:Wieso gibt's da keine betriebssystemunabhängige Implementierung in Python?
@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.
Nur schade, daß da für das Einlesen jedes einzelnen Zeichens die Terminal-Einstellungen umgestellt werden.lunar hat geschrieben:Das geht kürzer, eleganter und allgemein besser.
(Außerdem beruht die dort genannte Funktion ebenfalls auf dem dort weiter oben gezeigten KeyHandler-Code.)
Gruß
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).
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).
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 ), 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
@problembär:
Ich hab Deine Version nicht mehr parat (und den Link nicht verfolgt ), 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
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ß
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ß
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.
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.
Klassen verbinden Daten und zugehöriges Verhalten und sind nicht bloß Namensräume für Funktionen.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 ...
Es kann durchaus mal wichtig sein: "__exit__" wird nicht in jedem Fall aufgerufen. *POWER OFF*.lunar hat geschrieben:Durch die Verwendung der with-Anweisung ist garantiert, dass das Terminal unter allen Umständen wieder in den Ausgangszustand versetzt wird.
Das Leben ist wie ein Tennisball.