stdin und "Ctrl + D"

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.
Lu_python
User
Beiträge: 7
Registriert: Donnerstag 2. November 2023, 17:08

Hallo,

ich habe ein banales Problem und komme dennoch nicht weiter. Folgender hochkomplexer Code:

import sys
print(sys.stdin.read())

startet vom Terminal ganz wunderbar. Ich komme aber nicht "raus", und entsprechend wird auch nichts gedruckt. Was muss ich tun?
Youtube sagt mir "Ctrl+D", Google fördert noch zu Tage, dass sei für Unix, und bei Windows solle man strg+z drücken.
Funzt nicht. Egal, ob ich das z klein oder das Z groß wähle. d und D: gleiches Ergebnis.
Es gibt so Tage, da fühle ich mich wirklich .....

LG Lu
Python 3.12
Windows 10
PyCharm 2023.2.3 Community Edition
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe schon mal das Problem unter Windows gehabt, dass der Interpreter nicht interaktiv war, und ich dann auch nicht rauskam. Versuch mal "python -i", ggf "python -i mein-skript.py". Und dann sollte es eigentlich mit C-z klappen, ein bisschen C-c reinwerfen schadet auch nicht.
Lu_python
User
Beiträge: 7
Registriert: Donnerstag 2. November 2023, 17:08

Hej, das war auf jeden Fall ein Fortschritt! Immerhin komme ich jetzt "raus"!
Vielen Dank Dir!

Allerdings arbeitet die stdin.read-Geschichte nicht, so sieht es auf der Konsole jetzt aus:
python -i main.py
meine sinnlose Texteingabe
meine auch nicht sinnvollere, zweite Texteingabe
Traceback (most recent call last):
File "C:\Users\[...]\main.py", line 8, in <module>
print(sys.stdin.read())
^^^^^^^^^^^^^^^^
KeyboardInterrupt

nach meinem Verständnis diverser Tutorials hätte nun aber
print(sys.stdin.read())
dazu führen sollen, dass genau das gleiche wieder ausgegeben wird, nicht aber ein Error wie zu sehen
nur für die ganz Doofen (also mich und ein paar wenige): mit C-c meinst Du "Strg+c", korrekt?

LG Lu
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Du brichst das Skript ab bevor das print ausgeführt wird.
Manul
User
Beiträge: 53
Registriert: Samstag 13. Februar 2021, 16:00

Zumindest das Ctrl-D unter Unix funktioniert nur am Anfang einer neuen Zeile - vielleicht ist das mit dem Ctrl-Z unter Windows ja genauso.
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

Und weil du PyCharm erwähnt hast: Dessen integriertes Terminal verhält sich manchmal nicht so, wie man das von einem Terminal erwarten würde. Also vielleicht auch mal außerhalb von PyCharm ausprobieren, ob da ein Ctrl-Z funktioniert.

Und ja, C-c heißt Ctrl-C, kommt AFAIK von Emacs, wo das so benannt wurde.
Lu_python
User
Beiträge: 7
Registriert: Donnerstag 2. November 2023, 17:08

Tjaaaaa ..... ich komme Dir jetzt vielleicht SEHR blöde vor, aber ich habe keine Ahnung, was Du meinst. Wie kann ich denn das Skript abbrechen, bevor print ausgeführt wird, wenn Print doch der einzige Befehl im ganzen Programm ist? Na gut, "import sys" gibt es natürlich auch noch ....
Ich habe das Ganze so verstanden, dass ich das Programm starte, dann 'was-auch-immer' eingebe, im Zweifel auch mehrere Zeilen (sieht man ja in meinem Post von 18:27) und das man dann, um die Eingabe zu beenden und die Wiedergabe am Bidlschirm zu starten (denn das ist doch der Sinn des Print-Befehls, oder?) C-c drücken soll .... mache ich, und dann kommt die Fehlermeldung. Wann soll ich denn stattdessen C-c drücken, wenn nicht am Ende der Eingabe? Oder was soll ich stattdessen zum Beenden der Eingabe drücken, wenn nicht C-c?
Deine Anregung, es noch mal ohne PyCharm zu verscuhen, habe ich umgesetzt (in der Windows Eingabe-Aufforderrung). da komt dann:
python -i main.py
dfsfsdfsdfsdf
sdfsdfsdfsdf
Traceback (most recent call last):
File "C:\Users\PycharmProjects\pythonProject2\main.py", line 8, in <module>
print(sys.stdin.read())
^^^^^^^^^^^^^^^^
KeyboardInterrupt

also ziemlich das Gleiche wie unter PyCharm, nur dass ich Freitag anderen Text hatte ....

LG Lu
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du irgendwann mal return gedrueckt?
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Lu_python hat geschrieben: Montag 6. November 2023, 15:11 Wie kann ich denn das Skript abbrechen, bevor print ausgeführt wird, wenn Print doch der einzige Befehl im ganzen Programm ist? Na gut, "import sys" gibt es natürlich auch noch ....
Vor dem `print` wird zunächst `sys.stdin.read()` ausgeführt und das brichst du ab.
Lu_python
User
Beiträge: 7
Registriert: Donnerstag 2. November 2023, 17:08

Return habe ich gedrückt, um von einer Zeile in die andere zu kommen (Du kannst sehen, dass meine Eingabe zwei-zeilig ist - genau das soll ja auch der Vorteil von stdin sein, dass man mehrzeigilig eingeben kann).

Aber noch einmal nachgefragt: wann soll ich denn DANN C-c drücken, wenn nicht am Ende der Eingabe?
Oder was soll ich STATTDESSEN drücken, um die Eingabe zu beenden?
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na return innerhalb der gewünschten Eingabe, wenn das Programm läuft. Terminals liefern oft nicht jedes Zeichen, sondern erst eine ganze Zeile wird weiter gegeben. Vorher kehrt read ggf nicht zurück. Rein von der API her muss read gar nicht wiederkehren zwischendurch,, sondern erst beim EOF. Was jetzt ja etwas schwierig ist, das Programm läuft die ganze Zeit, und stdin ist mit dem terminal verbunden. Unter Unix kann man dann ggf. mit C-d EOF schicken, ob das unter Windows geht - keine Ahnung.

Summa summarum: das ist nicht ganz so trivial wie du denkst, weil read dann sehr von der Umgebung abhängig ist. Sich daran festzubeißen ist vielleicht einfach auch etwas Verschwendung.
Lu_python
User
Beiträge: 7
Registriert: Donnerstag 2. November 2023, 17:08

danke für Deine Einschätzung .... ich wollte halt nur mal etwas "ganz einfaches" mit stdin ausprobieren, und wenn ich daran schon komplett scheitere, weiß ich nicht, ob ich mich an komplexeres traue ..... :-(
__deets__
User
Beiträge: 14544
Registriert: Mittwoch 14. Oktober 2015, 14:29

stdin/stdout sind unter Windows nicht so einfach. Leider. Erst recht nicht, wenn man dann in Dateiumleitungen etc geht. Aber man muss sich darueber auch nicht graemen. Das ist nun wirklich nur eine kleine Ecke, und man kann wunderbar python programmieren, ohne das gemeistert zu haben.
Lu_python
User
Beiträge: 7
Registriert: Donnerstag 2. November 2023, 17:08

:-)
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Haben wir denn jetzt tatsächlich ganz sicher die Variante: Text eingeben und dann Strg+Z und jetzt wichtig: Enter als letzter Eingabe/Taste zwischen Texteingabe und Strg+Z durch? Weil *das* in der Eingabeaufforderung von Windows eigentlich funktionieren sollte.

Zu der Frage das `print()` nicht das erste ist was ausgeführt wird, wollte ich noch den Bytecode zeigen, aber da sieht man das nicht ganz so deutlich wie erhofft. Also man sieht das da natürlich schon, dass die Funktion als letztes aufgerufen wird, aber das Funktionsobjekt wird ”leider” als allererstes auf den Stapel geladen:

Code: Alles auswählen

In [367]: import dis

In [368]: def f():
     ...:     print(sys.stdin.read())
     ...: 

In [369]: dis.dis(f)
  2           0 LOAD_GLOBAL              0 (print)
              2 LOAD_GLOBAL              1 (sys)
              4 LOAD_ATTR                2 (stdin)
              6 LOAD_METHOD              3 (read)
              8 CALL_METHOD              0
             10 CALL_FUNCTION            1
             12 POP_TOP
             14 LOAD_CONST               0 (None)
             16 RETURN_VALUE
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Lu_python
User
Beiträge: 7
Registriert: Donnerstag 2. November 2023, 17:08

Hallo Blackjack,

Du schreibst jetzt "in der Eingabeaufforderung " .... es sollte ursprünglich aber als Programm "main-py" funktionieren, dass dann aus der Eingabe-Aufforderung heraus aufgerufen wird ... aber ich habe mich jetzt eigentlich schon damit angefreundet, dass ich da zu tief schürfe :-)

LG Lu
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich glaube, dein Problem wurde nicht so ganz erfasst. Es geht um PyCharm unter Windows und du hast innerhalb der PyCharm-Umgebung ein Programm, das print(sys.stdin.read()) ausführt, richtig? Dann funktioniert Strg+Z tatsächlich nicht, wenn man es mit PyCharm laufen lässt. Habe ich gerade selber ausprobiert. Das dürfte eine spezielle Sache von PyCharm sein. Ich weiß nicht, ob das gewollt oder ein Bug ist.

Jedenfalls, wenn man unten in PyCharm auf das Terminal-Symbol klickt und eine PowerShell-Instanz kriegt, dann kann man dort Python ausführen und im interaktiven Interpreter das print(sys.stdin.read()) ausführen. Dort funktioniert Strg+Z (zumindest bei mir) wie gewünscht. Insofern scheint PyCharm durchaus das "Windows-Verhalten" zu können. Vielleicht muss man auch nur igendwo etwas in den Einstellungen ändern...

EDIT: Strg+D funktioniert aber. Es scheint als hat man bei laufenden PyCharm-Programmen nur "Linux-Verhalten" in Bezug auf die Terminal-Sequenzen.

Aber bei dir klappt Strg+D auch nicht?
juwido
User
Beiträge: 20
Registriert: Donnerstag 15. Dezember 2022, 13:41

Das Problem ist doch, das allgemein die Terminal-Programme nicht einzelne Zeichen weitergeben, sondern zunächst die Eingabezeile editierbar ist. Die Weitergabe der Zeichenfolge erfolgt dann mit der Eingabetaste (Enter/Return) und inklusive des End-Of-Line Zeichens.
Ist keine Anzahl Zeichen bei read() angegeben, so muß die Zeichenfolge aber mit End-Of-File enden, also vor dem letzten Return.
Dabei ist zu beachten, das die mit Ctrl.+ .. eingegebenen Steuerzeichen vom Terminal auch weitergegeben werden müssen. Das könnten auch Shortcuts sein, die das Terminal "schluckt". Ctrl.+c ist in Windows beispielsweise auch gerne mal "copy" .
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dass man nach dem EOF noch Enter drückt, hatte ich mal vorausgesetzt. Aber stimmt, das ist vielleicht dem TE nicht klar gewesen. Warten wir mal auf seine Reaktion...
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ui, *das* war mir jetzt nicht so klar. Unter Linux ist das nicht so. Da ist das aber auch nicht wirklich ein Zeichen. Und ich wäre bis eben auch davon ausgegangen, dass das auch unter Windows nur die Aufforderung an die Konsole ist, die Datei zu `stdin` vom in ihr laufenden Programm zu schliessen. Aber unter Windows kann das ja tatsächlich sein, dass da noch das Strg-Z-Zeichen (Byte 0x1A) in `stdin` vom anderen Prozess geschrieben wird.

Geerbt von DOS. Was das wiederum von CP/M geerbt hat. Und CP/M hat das weil unter CP/M Dateien nur in Blöcken von (üblicherweise) 128 Bytes gelesen und geschrieben werden und Dateigrössen nicht bytegenau, sondern als Anzahl dieser Blöcke ”gemessen” werden. Da Textlängen selten glatt durch 128 teilbar sind, braucht man ein Steuerzeichen welches das Ende der Textdaten im letzten Block markiert: 0x1A (dezimal 26), Eingabe über Strg-Z. Angezeigt unter DOS, falls Steuerzeichen als Text dargestellt werden, als ``→``.

Interessant was man immer noch so an Entwicklungsgeschichte mitschleppt. 🤓
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten