2010-05-17 14 views
21

Ist es möglich, stdin als Binärdaten in Python 2.6 zu lesen? Wenn das so ist, wie?Binärdaten von stdin lesen

Ich sehe in der Python 3.1 documentation, dass dies ziemlich einfach ist, aber die Möglichkeiten dafür 2.6 scheint nicht da zu sein.

Wenn die in 3.1 beschriebenen Methoden nicht verfügbar sind, gibt es eine Möglichkeit, Stdin zu schließen und im Binärmodus wieder zu öffnen?

aktualisiert

Nur klar zu sein, ich bin mit ‚Typ‘ in einem MS-DOS-Shell Rohr des Inhalts einer Binärdatei in meinem Python-Code. Dies sollte dem Unix-Befehl 'Katze' entsprechen, soweit ich es verstehe. Aber wenn ich das auschecke, bekomme ich immer ein Byte weniger als die erwartete Dateigröße.

Update # 2

Zunächst einmal vielen Dank für die Antworten. Ich arbeite langsam an einer echten, brauchbaren Lösung. Am Ende versuche ich immer noch, eine in sich geschlossene JAR-Datei zu erstellen, die meinen Python-Code automatisch ausführt und alle Befehlszeilenargumente ohne Fehler übergibt.

Der Grund, warum ich die Java/JAR/Jython-Route gehe, ist, weil eine meiner externen Hauptbibliotheken nur als Java JAR verfügbar ist. Aber leider hatte ich meine Arbeit als Python begonnen. Es wäre vielleicht einfacher gewesen, meinen Code vor einiger Zeit auf Java zu konvertieren, aber da dieses Zeug eigentlich kompatibel sein sollte, dachte ich mir, ich würde versuchen, es durchzugehen und zu beweisen, dass es möglich ist.

Für den Fall, dass sich jemand fragen würde, hängt dies auch mit der Frage zusammen, die ich vor ein paar Tagen gestellt habe.

Packaging and deploying a Jython program from Eclipse

Einige dieser Frage wurde in dieser question beantwortet.

Also werde ich versuchen, meine ursprüngliche Frage mit einigen Notizen zu aktualisieren, was ich bis jetzt herausgefunden habe.

Antwort

13

Verwenden Sie die -u command line switch, um Python 2 zu zwingen, stdin, stdout und stderr als binäre ungepufferte Streams zu behandeln.

C:> type mydoc.txt | python.exe -u myscript.py 
+0

Ich habe dies mit "Typ" getestet und es scheint zu funktionieren. Das heißt, wenn ich das -u-Flag weglasse, bekomme ich ein Zeichen weniger pro Zeile. –

+0

Kühl. Danke für den Test. Also, nur weil ich dich so sehr mag, jede Idee, wie die Option '-u' durch die JarRunner.java-Klasse übergeben wird, die verwendet wird, um Jython durch eine ausführbare JAR-Datei auszulösen? Ich weiß. Ich mache nie etwas auf die leichte Art. – thebeav

+1

Laut der Dokumentation hat das Festlegen der Umgebungsvariable PYTHONUNBUFFERED denselben Effekt. Nicht sicher, ob das hilft. –

-2
import sys 

data = sys.stdin.read(10) # Read 10 bytes from stdin 

Wenn Sie Binärdaten interpretieren müssen, verwenden Sie das Modul struct.

+0

Wenn ich dann sys.stdin.read() aufrufen, ohne Parameter, sollte es lese alle binären Daten, die eingegeben wurden, richtig? Wie berechne ich dann die Länge richtig? len (data) gibt den falschen Wert zurück, wenn das letzte Byte der Daten eine Null war. Wie überprüfen und korrigieren Sie diese Situation? – thebeav

+1

'len' zählt die \ x00 Zeichen in der Zeichenfolge. Python hat keine nullterminierten Strings. 'len (" Hallo \ x00 ") == 6' –

+0

Ich frage mich dann, ob es der 'type' Befehl aus der MS-DOS-Shell sein könnte, der den Verlust des letzten Bytes verursacht? Ich denke, ich werde das Äquivalent unter Linux testen müssen. Vielen Dank. – thebeav

9

Wenn Sie dies noch brauchen ... Dieser einfache Test ich verwendet habe, binäre Datei zu lesen, die 0x1A Zeichen zwischen

import os, sys, msvcrt 

msvcrt.setmode (sys.stdin.fileno(), os.O_BINARY) 
s = sys.stdin.read() 
print len (s) 

Meine Testdatei Daten enthält, war:

0x23, 0x1A, 0x45 

Ohne stdin in den binären Modus zu setzen, druckt dieser Test 1, sobald 0x1A als EOF behandelt wird. Natürlich funktioniert es nur auf Windows, weil es auf msvcrt-Modul abhängt.

+1

Aber Windows ist das einzige System, bei dem die meisten Leute ein Problem haben, daher sollte dies eine akzeptable Lösung sein. –

+1

Dies ist die richtige Lösung für Python 2, um die rohen Bytes von stdin unter Windows abzurufen. Unter Unix gibt es keinen Unterschied zwischen Binär- und Normalmodus. Siehe diesen Thread: http://code.activestate.com/lists/python-list/20426/ (stdin im rohen (binären) Modus wieder öffnen?) –

+0

Siehe auch http://cygwin.com/cygwin-ug- net/using-textbinary.html –

17

Aus der Dokumentation (siehe here):

The standard streams are in text mode by default. To write or read binary data to these, use the underlying binary buffer. For example, to write bytes to stdout, use sys.stdout.buffer.write(b'abc') .

Aber, wie in der akzeptierten Antwort unter Berufung auf Python mit einem -u ist eine weitere Option, die stdin, stdout und stderr zwingt völlig ungepufferte zu sein. Weitere Informationen finden Sie auf der Hilfeseite python (1).

Weitere Informationen zur Textpufferung finden Sie unter documentation on io. Verwenden Sie sys.stdin.detach(), um die Pufferung in Python zu deaktivieren. Hier

+6

dieses Dokument führt zu py3k docs, nicht, was das OP behandeln möchte. –

+1

Ich habe '-u' mit Python v3.2.5 versucht, aber es hat nichts nützliches getan. Aber die Verwendung von 'sys.stdout.buffer' funktioniert ziemlich gut, obwohl es in Python 2.7.8 kein solches Feature gibt. – ony

+0

Die Frage des OP war über Python 2.6. – Yuval

13

ist der letzte Schnitt für Linux/Windows-Python 3.2 kompatiblen Code, um Daten von stdin ohne Korruption zu lesen:

import sys 

PY3K = sys.version_info >= (3, 0) 

if PY3K: 
    source = sys.stdin.buffer 
else: 
    # Python 2 on Windows opens sys.stdin in text mode, and 
    # binary data that read from it becomes corrupted on \r\n 
    if sys.platform == "win32": 
     # set sys.stdin to binary mode 
     import os, msvcrt 
     msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) 
    source = sys.stdin 

b = source.read()