Socket Verbindung -Problem beim warten auf den Marker

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Black Panther
User
Beiträge: 27
Registriert: Samstag 11. Juni 2016, 19:09

Hallo,

kurze Frage zu User Inputs über Keyboard oder Scanner. Die normale und gängige Methode scheint es über raw_input() zumindest bei Python 2.7 so, den Input aufzugreifen. Automatisch wird aber alles was ich vorher eingegeben habe auch mit aufgegriffen. Gibt es eine Möglichkeit den Speicher zu löschen?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Black Panther: das hat jetzt nicht wirklich etwas mit der ursprünglichen Frage zu tun.
Normalerweise will man ja nicht, dass Eingaben verloren gehen. Das heißt, man macht irgendetwas, währenddessen kann der Nutzer schon etwas eingeben und irgendwann wird per raw_input() die Daten gelesen. Ich dachte, Du willst das ganze headless betreiben, so dass eigentlich nur Daten vom Scanner kommen. Und auch falls nicht, so kann der Nutzer immer noch Kommandos eingeben, die irgendetwas bewirken. Warum willst Du also den Speicher löschen?
Black Panther
User
Beiträge: 27
Registriert: Samstag 11. Juni 2016, 19:09

@Sirius3 ...ich wollte einfach keinen weiteren Thread eröffnen. In der Tat hast du Recht, wenn du davon ausgehst, dass der Usser durch den Scanner Eingaben bei mir tätigt. Warum funktioniert raw_input() nicht zu dem Zeitpunkt der Abfrage, sondern zeichnet alles auf was der User auch schon vorher eingibt, während andere Funktionen von mir ablaufen?
SO wäre es möglich ein Haufen Serienummern einzuscannen und dann würde bei raw-Input() nur unverständliches übergeben werden.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Black Panther: normalerweise sollte der User gar keine Möglichkeit haben einen Haufen Seriennummern einzuscannen, weil das Abarbeiten normalerweise so kurz ist, dass das Programm gleich wieder in raw_input hängt und umgekehrt wäre es ja blöd, wenn der Nutzer etwas scannt, das Programm aber gerade für eine Millisekunde nicht bereit ist, und deshalb die Eingabe verwirft. Der Scanner sollte eigentlich klar abgetrennte Seriennummern senden, so dass nichts unverständliches gelesen wird, sondern nur ein Haufen Seriennummern, und falls doch etwas unverständliches kommt, sollte das Programm darauf reagieren können, z.B. in dem es nervös rot blinkt und die Anfrage dann ignoriert.
Black Panther
User
Beiträge: 27
Registriert: Samstag 11. Juni 2016, 19:09

@Sirius3....ich kann alles nachvollziehen was du mir schilderst.
Fakt ist: Es kommt ein Sensor zum Einsatz, wenn der nicht betätigt ist wartet nun einmal das Programm. In der Zeit ist es möglich das der User aus unsinniger Art und Weise heraus etwas einscannt (vielleicht auch vermehrt). Meine Frage noch einmal konkretisiert: Wie kann man den Speicher auf den raw_input() zurückgreift kurz vorher löschen? Sodass nur auf die konkrete Nachfrage eine Eingabe beachtet wird. Das ist ein sehr elementares Problem, was schon im deutschen und englischen Raum scharf diskutiert wurde.


Leider ist mir keine Lösung bisher entgegen geflogen, so dass ich nach Hilfe fragen muss.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Black Panther: damit ich das richtig verstehe:
  1. Sensor wird aktiviert
  2. Eingabepuffer leeren
  3. Warten auf Scanner
  4. User scannt
  5. Aktion durchführen
  6. wieder von vorne
Somit werden erst Eingaben angenommen, wenn der Sensor aktiviert ist und kein User wundert sich, dass Dinge, die vorher gescannt wurden ignoriert werden.

Code: Alles auswählen

def flush():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    termios.tcsetattr(fd, termios.TCSAFLUSH, old_settings)
Black Panther
User
Beiträge: 27
Registriert: Samstag 11. Juni 2016, 19:09

@Sirius...ist genau das, was ich meinte. Interessant ist halt der Punkt 2 (Eingabepuffer löschen). Im Allgemeinen verstehe ich nicht, warum die Funktion raw_input() auf den kompletten Eingabepuffer zurückgreift und nicht nur für den moment der Aktivierung angreift.

Zu der Definition von flush() würde ich gerne Verständnisfragen stellen.
1.) Ziele 2: Du speicherst sys.stdin.fileno() in der Varaible fd (filedescriptor). Laut google gibt es für den sys.stdin.fileno() 3Stufen, nämlich 0, 1, and 2 represent standard input, standard output, and standard error. Im Endeffekt sagst du Python lese etwas ein oder?
2.) termios.tcgetattr(fd) verstehe ich garnicht. Verfolgt anscheinend viele Attribute wie Flag, Länge usw. von fd.
3.) termios.tcsetattr() ....durch das Flush würde ich sagen, dass du die Input Welle zurücksetzt.

Fazit:
FÜr mich persönlich relativ schwer, weil ich es nicht komplett nachvollziehen kann. GIbt es eine einfachere Vorstufe davon?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Black Panther: das Problem ist, dass es nichts einfaches gibt, wie man den Terminal-Inputpuffer löschen kann, weil das normalerweise niemand braucht. Da muss man schon mit ein paar Einstellungen spielen, wobei hier die Einstellungen gar nicht geändert werden, sondern nur die aktuellen neu gesetzt werden. Was da also alles in settings steht, ist irrelevant. Eine der seltenen Anwendungen ist getpass, um Passwörter einzugeben, wo Du im Quellcode im Prinzip die selben Funktionen findest.
Black Panther
User
Beiträge: 27
Registriert: Samstag 11. Juni 2016, 19:09

@Sirius.... heftig, dass es so ein Problem ist . Ich kann ja nicht einmal genau die Länge einer EIngabe definieren, weil die schwankt. raw_input ist Bestandteil jedes Basistutorials von daher hätte ich schon gedacht, das es öfter verwendet wird.
Anders herum gefragt: Ist es möglich die Eingabe zu blockieren bis zu der gewünschten Funktion?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Black Panther: Du hast eine Lösung. Was fehlt Dir noch?
BlackJack

@Black Panther: Das was öfter verwendet wird? `raw_input()`? Das wird öfter verwendet. Nur will niemand, oder zumindest kaum jemand, Eingaben einfach ignorieren. In 99,9% der Fälle will man alles verarbeiten was der Benutzer eingibt. Oder man kann zumindest gezielt überlesen was einen nicht interessiert.
Black Panther
User
Beiträge: 27
Registriert: Samstag 11. Juni 2016, 19:09

@Sirius...hab deinen Code probiert. Ergebnis: UnsupportedOperation: fileno ( im Bezug auf fd =sys.stdin.fileno()) Ist das Modul tcflush kein Grundpaket von Python 2.7?

Desweiteren habe ich folgenden Code aus dem Netz getestet:

Code: Alles auswählen

from termios import tcflush, TCIFLUSH
import time,sys

a = raw_input("first input ")
b = raw_input("second input ")

time.sleep(5)
tcflush(sys.stdin, TCIFLUSH)

a = raw_input("third input ")
b = raw_input("fourth input ")
Mit dem Ergebnis: UnsupportedOperation: fileno
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Black Panther: genau das ist das Problem mit Terminals, dass sie vorhanden sein müssen um zu funktionieren. Lass mich raten: Du startest das Programm aus einer IDE heraus?
Black Panther
User
Beiträge: 27
Registriert: Samstag 11. Juni 2016, 19:09

@Sirius.... Dachte die Shell auf dem Raspberry verhält sich genauso. Im Bereich Terminal geht die Lösung perfekt. Wobei man sagen muss, der EIngabespeicher wird nicht gelöscht, sondern das vorhergehende wird übersprungen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Black Panther: von welcher Shell redest Du? Und was meinst Du, dass der Eingabespeicher nicht gelöscht sondern nur übersprungen wird?
Black Panther
User
Beiträge: 27
Registriert: Samstag 11. Juni 2016, 19:09

@Sirius.... die Python Shell vom Raspberry Pi 2 Model B mit Betriebssystem Jessie. Ich glaube, dass mit dem Eingabespeicher kann ich am besten an einem Beispiel erklären. Wenn ich 4x raw_input und zwischen dem zweiten und dem dritten einlesen einen timeout und flush() setze, dann kann ich ja trotzdem EIngaben tätigen: (fortlaufend erscheint das im Terminal)
1. erster Input:1929218210
2. zweiter Input: 992398239
89239802898932 3.dritter Input: 982939828932
4.vierter Input: 929923289


"89239802898932" wurde von mir während des timeouts eingegeben. Der dritte INput schiebt sich an das Ende der EIngabe und "ignoriert"quasi das davor. Meine nicht fachliche Beschreibung liegt aber fehlenden Verständnis für die Funktion...aber sie erfüllt das was ich erwartet habe.

LG
Black Panther
BlackJack

@Black Panther: Ja, Du kannst Eingaben tätigen, aber die werden aus dem Eingabepuffer des Terminals *gelöscht*. Was *angezeigt* wird, ist noch einmal etwas völlig anderes. Wenn Du den Puffer löschst, dann hat das keinen Einfluss auf die Anzeige des Terminals. Das wäre auch schwierig, denn dann müsste das Terminal sich ja jede Änderung merken, oder zumindest ein “diff“ davon um das rückabwickeln zu können. Du betrachtest da nur ein paar Ziffern, und denkst die können einfach entfernt werden. Ja könnten sie, aber Du kannst während der Wartezeit ja auch zig mal die Eingabetaste drücken, so dass der ganze Terminalinhalt nach oben raus gescrollt wird. Das liesse sich nicht mehr so einfach rückgängig machen. Das geht auch ein bisschen über den Aufgabenbereich eines Terminals hinaus.

Wenn von `sys.stdin` keine Dateinummer abgefragt werden kann, dann handelt es sich bei dem Objekt nicht um eine Datei im Betriebssystem-Sinn und damit auch ganz sicher nicht um ein Terminal. Das ist in der Regel in IDEs der Fall wo die Eingabe aus einem Fenster oder Texteingabefeld kommt. Man muss das schon auf der Linux-Konsole oder einem Terminal-Emulator wie ``lxterm`` aus starten damit `sys.stdin` mit einem (Pseudo)Terminal verbunden ist.
Antworten