[Linux] Einzelnes Zeichen lesen

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
DominikST
User
Beiträge: 3
Registriert: Sonntag 20. Mai 2012, 09:56

Hey Leute,

für ein kleines, konsolenbasiertes Spiel müsste ich ein einzelnes Zeichen von der Tastatur lesen. Es erscheint also eine Meldung auf dem Bildschirm und sobald der Benutzer ein Zeichen eintippt wird dieses Zeichen gespeichert und das Programm geht weiter, <Enter> muss zur Bestätigung nicht gedrückt werden. Geht sowas?

Betriebssystem ist Ubuntu 12.04, Python Version ist egal, 3.2 kann ich ein bisschen besser.

Danke schonmal
DominikST
User
Beiträge: 3
Registriert: Sonntag 20. Mai 2012, 09:56

Sehr gut, das Lesen klappt schonmal. Wie setze ich den Terminal-Modus nun wieder auf normal? Wenn ich nämlich das Spielfeld zeichne ist es extrem verzerrt...
deets

hm, vielleicht ist es besser gleich auf ncurses zu setzen?
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

DominikST hat geschrieben:Wie setze ich den Terminal-Modus nun wieder auf normal?
Versuch doch mal, den Code selbst nachzuvollziehen. Neben `tcgetattr()` gibt es im Modul termios auch die Funktion `tcsetattr()`. Dreimal darfst du raten, welche Attribute da wohl reingehören. Kleiner Tipp: Das Snippet bereitet das weitere Vorgehen quasi schon vor, aber hört dann irgendwie abrupt auf (warum auch immer).
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@lunar: Warum verwendest du kein `tty.setraw()`?
lunar

@snafu: Ich wusste gar nicht nicht, dass es das gibt. Das Beispiel habe ich direkt von C übertragen, ohne mir weitere Gedanken zu machen. Ich habe das Beispiel aktualisiert, so dass es "tty.setraw()" benutzt.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Auch wenn schon etwas angestaubt - hier hatte ich mich mal an getch, getwch, kbhit und einem Kontextmanager für Terminalmodi probiert.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

lunar hat geschrieben:@snafu: Ich wusste gar nicht nicht, dass es das gibt. Das Beispiel habe ich direkt von C übertragen, ohne mir weitere Gedanken zu machen.
Auf C-Ebene gibts doch mit `cfmakeraw()` etwas ähnliches, oder bringe ich da grad was durcheinander?
lunar

@snafu: Auch das kannte ich nicht, denn auch der C-Code, den ich als Vorlage verwendet habe, stammt nicht von mir. ;)
DominikST
User
Beiträge: 3
Registriert: Sonntag 20. Mai 2012, 09:56

@All

Danke, lunars Beispiel funktioniert ;)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich würde ebenfalls empfehlen, http://docs.python.org/library/curses.html zu benutzen, und nicht am Terminal auf der wirklich untersten Betriebssystemebene zu fummeln. Curses versucht ja gerade, von den Eigenheiten der Terminals zu abstrahieren und läuft zumindest problemlos unter allen Unix-artigen Betriebssystemen inklusive OS X. Einig für Windows muss man etwas tun (siehe http://www.lfd.uci.edu/~gohlke/pythonlibs/#curses).

Stefan
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Beispiel mit curses:

Code: Alles auswählen

import curses

from sys import stdin, stdout


def read_character(prompt=''):
    print(prompt, end='')
    stdout.flush()
    curses.initscr()
    curses.cbreak()
    try:
        return stdin.read(1)
    finally: # Trick mit try / finally von Lunar
        curses.nocbreak()
        curses.endwin()
Nicht sehr schön, und auch langsam.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich finde, das `curses`-Beispiel ist auch nicht wesentlich "highleveliger" als der `tc[get|set]attr()`-Ansatz aus lunars Beispiel. Das genannte `tty.setraw()` übernimmt nochmal das Setzen der passenden Attribute für einen, sodass man zumindest keine Konstanten und deren Anwendung auswendig wissen (bzw per Copy&Paste einfügen) muss.

Man kann's natürlich auch mit `curses` machen und erstmal die Initialisierungsroutine der Bibliothek aufrufen und so, aber soviel gewonnen ist dadurch glaube ich auch nicht.

Es kommt natürlich immer darauf an, ob man wirklich nur diese eine Sache machen möchte, oder ob man `curses` - wenn einmal initialisiert - nicht auch für weitere ähnliche Aktionen im Programm verwenden will.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Ich weiss nicht, ob der Bug im curses-Modul noch existiert, allerdings ging früher das wiederholte Initialisieren des Terminalscreens nicht, sondern quittierte das ab dem 2nd Versuch mit einem segfault, während in C das kein Problem ist.
Antworten