Scriptaufruf klappt als User, scheitert als root (stdin.read und Nicht-Unicode)

27/02/2009 - 02:40 von Hauke Laging | Report spam
Moin,

ich habe kürzlich mein erstes Python-Programm zu Ende gekàmpft - es
funktioniert sogar (wenngleich mir nicht im gewünschten Umfang klar
ist, wieso eigentlich).

Das Programm liest ein Vielfaches der angegebenen Blocklànge von
stdin, erzeugt dann das XOR über alle Blöcke und gibt das Ergebnis
aus. Ich habe das Script als normaler User geschrieben und kann es
erfolgreich starten.

Wenn ich es jedoch als root starte, passiert Absonderliches:

# cat keyfile.test.* | ~hl/scripts/xor.py 32 > keyfile.test.tmp
Traceback (most recent call last):
File "/home/hl/scripts/xor.py", line 31, in <module>
input = sys.stdin.read(keylength)
File "/usr/lib64/python3.0/io.py", line 1728, in read
eof = not self._read_chunk()
File "/usr/lib64/python3.0/io.py", line 1557, in _read_chunk
self._set_decoded_chars(self._decoder.decode(input_chunk, eof))
File "/usr/lib64/python3.0/codecs.py", line 300, in decode
(result, consumed) = self._buffer_decode(data, self.errors,
final)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-2:
invalid data

Öhm.

Dass die Eingabedaten kein Unicode sind, ist klar. Hàlt
sys.stdin.read die Eingabe zwingend für Unicode? Und warum nur beim
Aufruf als root?

Wie kriege ich die Daten denn nun "als Bytes" in mein Script? Das
read hat hier jemand vorgemacht (zwar nicht von stdin, sondern aus
einer Datei, aber das sollte ja wohl egal sein. Ich habe hier auch
struct und (un)pack als Tipps bekommen, aber erst mal müssen die
Daten es ja ins Programm schaffen...


CU

Hauke
http://www.hauke-laging.de/ideen/
 

Lesen sie die antworten

#1 Peter Otten
27/02/2009 - 11:03 | Warnen spam
Hauke Laging wrote:

Moin,

ich habe kürzlich mein erstes Python-Programm zu Ende gekàmpft - es
funktioniert sogar (wenngleich mir nicht im gewünschten Umfang klar
ist, wieso eigentlich).

Das Programm liest ein Vielfaches der angegebenen Blocklànge von
stdin, erzeugt dann das XOR über alle Blöcke und gibt das Ergebnis
aus. Ich habe das Script als normaler User geschrieben und kann es
erfolgreich starten.

Wenn ich es jedoch als root starte, passiert Absonderliches:

# cat keyfile.test.* | ~hl/scripts/xor.py 32 > keyfile.test.tmp
Traceback (most recent call last):
File "/home/hl/scripts/xor.py", line 31, in <module>
input = sys.stdin.read(keylength)
File "/usr/lib64/python3.0/io.py", line 1728, in read
eof = not self._read_chunk()
File "/usr/lib64/python3.0/io.py", line 1557, in _read_chunk
self._set_decoded_chars(self._decoder.decode(input_chunk, eof))
File "/usr/lib64/python3.0/codecs.py", line 300, in decode
(result, consumed) = self._buffer_decode(data, self.errors,
final)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-2:
invalid data

Öhm.

Dass die Eingabedaten kein Unicode sind, ist klar. Hàlt
sys.stdin.read die Eingabe zwingend für Unicode? Und warum nur beim
Aufruf als root?



Hast Du Dein System vielleicht so (ver)konfiguriert, dass 'python' als root
auf Python 3.0 und als normaler User auf Python 2.x verlinkt?

Demo-Script:

$ cat read.py
import sys
print(repr(sys.stdin.read()))

Generiere eine Bytefolge, die kein gültiges UTF-8 darstellt:

$ python2.5 -c'open("tmp.txt", "w").write("".join(map(chr, range(128,
138))))'

$ cat tmp.txt | python2.5 read.py
'\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89'

$ cat tmp.txt | python3.0 read.py
Traceback (most recent call last):
File "read.py", line 2, in <module>
print(repr(sys.stdin.read()))
File "/usr/local/lib/python3.0/io.py", line 1724, in read
decoder.decode(self.buffer.read(), final=True))
File "/usr/local/lib/python3.0/codecs.py", line 300, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0:
unexpected code byte

In Python 3.0 wird stdin also in der Tat als UTF-8 (jedenfalls als Text
statt als Bytefolge) interpretiert.

Wie kriege ich die Daten denn nun "als Bytes" in mein Script? Das
read hat hier jemand vorgemacht (zwar nicht von stdin, sondern aus
einer Datei, aber das sollte ja wohl egal sein. Ich habe hier auch
struct und (un)pack als Tipps bekommen, aber erst mal müssen die
Daten es ja ins Programm schaffen...



Wenn das mit der Verwendung von Python 3 Absicht war:

$ cat readbytes.py
import sys
print(repr(sys.stdin.buffer.read()))
$ cat tmp.txt | python3.0 read.py
b'\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89'

Ich weiß allerdings nicht, ob das der offizielle Weg ist.

Peter

Ähnliche fragen