Frage Konvertieren von Bytes in eine Zeichenfolge?


Ich verwende diesen Code, um die Standardausgabe von einem externen Programm zu erhalten:

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]

Die Methode communicate () gibt ein Array von Bytes zurück:

>>> command_stdout
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

Ich möchte jedoch mit der Ausgabe als normale Python-Zeichenfolge arbeiten. Damit ich es so ausdrucken kann:

>>> print(command_stdout)
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2

Ich dachte, das ist was binascii.b2a_qp () Methode ist für, aber wenn ich es versuchte, bekam ich das gleiche Byte-Array wieder:

>>> binascii.b2a_qp(command_stdout)
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

Weiß jemand, wie man den Byte-Wert zurück in einen String konvertiert? Ich meine, benutze die "Batterien" anstatt es manuell zu machen. Und ich möchte, dass es mit Python 3 in Ordnung ist.


1236
2018-03-03 12:23


Ursprung


Antworten:


Sie müssen das Byte-Objekt dekodieren, um eine Zeichenfolge zu erzeugen:

>>> b"abcde"
b'abcde'

# utf-8 is used here because it is a very common encoding, but you
# need to use the encoding your data is actually in.
>>> b"abcde".decode("utf-8") 
'abcde'

2036
2018-03-03 12:26



Ich denke, dieser Weg ist einfach:

bytes = [112, 52, 52]
"".join(map(chr, bytes))
>> p44

119
2017-08-22 12:57



Sie müssen die Byte-Zeichenkette dekodieren und in eine Zeichenkette (Unicode-Zeichenkette) umwandeln.

b'hello'.decode(encoding)

oder

str(b'hello', encoding)

99
2018-03-03 12:28



Wenn Sie die Kodierung nicht kennen, dann verwenden Sie uraltes MS-DOS, um die binäre Eingabe in eine Python 3 und Python 2 kompatible Art zu lesen CP437 Codierung:

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

lines = []
for line in stream:
    if not PY3K:
        lines.append(line)
    else:
        lines.append(line.decode('cp437'))

Da die Codierung unbekannt ist, erwarten Sie, dass nicht-englische Symbole in Zeichen von cp437 (Englische Zeichen werden nicht übersetzt, da sie in den meisten Einzelbyte-Kodierungen und UTF-8 übereinstimmen).

Das Dekodieren von willkürlichen Binäreingaben in UTF-8 ist unsicher, weil Sie Folgendes bekommen können:

>>> b'\x00\x01\xffsd'.decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 2: invalid
start byte

Gleiches gilt für latin-1, das für Python 2 populär (Standard?) war. Siehe die fehlenden Punkte in Codepage-Layout - Hier erstickt Python mit berüchtigten ordinal not in range.

AKTUALISIEREN 20150604: Es gibt Gerüchte, dass Python 3 hat surrogateescape Fehlerstrategie für das Codieren von Daten in Binärdaten ohne Datenverlust und Abstürze, aber es erfordert Konvertierungstests [binary] -> [str] -> [binary] um Leistung und Zuverlässigkeit zu bestätigen.

UPDATE 20170116: Dank Kommentar von Nearoo - gibt es auch die Möglichkeit, alle unbekannten Bytes mit zu entziffern backslashreplace Fehlerbehandler. Das funktioniert nur für Python 3, daher erhalten Sie auch bei dieser Problemumgehung immer noch inkonsistente Ausgaben von verschiedenen Python-Versionen:

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

lines = []
for line in stream:
    if not PY3K:
        lines.append(line)
    else:
        lines.append(line.decode('utf-8', 'backslashreplace'))

Sehen https://docs.python.org/3/howto/unicode.html#python-s-unicode-support für Details.

UPDATE 20170119: Ich beschloss, Slash-Escaping-Dekodierung zu implementieren, die für Python 2 und Python 3 funktioniert. Es sollte langsamer sein cp437 Lösung, aber es sollte produzieren identische Ergebnisse auf jeder Python-Version.

# --- preparation

import codecs

def slashescape(err):
    """ codecs error handler. err is UnicodeDecode instance. return
    a tuple with a replacement for the unencodable part of the input
    and a position where encoding should continue"""
    #print err, dir(err), err.start, err.end, err.object[:err.start]
    thebyte = err.object[err.start:err.end]
    repl = u'\\x'+hex(ord(thebyte))[2:]
    return (repl, err.end)

codecs.register_error('slashescape', slashescape)

# --- processing

stream = [b'\x80abc']

lines = []
for line in stream:
    lines.append(line.decode('utf-8', 'slashescape'))

57
2017-12-17 14:23



Ich denke, was du eigentlich willst, ist folgendes:

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>> command_text = command_stdout.decode(encoding='windows-1252')

Aarons Antwort war korrekt, außer dass Sie wissen müssen, welche Kodierung verwendet werden soll. Und ich glaube, dass Windows 'Windows-1252' verwendet. Es spielt nur eine Rolle, ob Sie in Ihrem Inhalt ungewöhnliche (nicht-ASCII-) Zeichen haben, aber dann wird es einen Unterschied machen.

By the way, die Tatsache, dass es wichtig ist, ist der Grund, dass Python zu zwei verschiedenen Arten für Binär-und Text-Daten verwendet: es kann nicht magisch zwischen ihnen konvertieren, weil es die Codierung nicht kennt, es sei denn, Sie sagen es! Die einzige Möglichkeit, die Sie kennen würden, ist, die Windows-Dokumentation zu lesen (oder sie hier zu lesen).


32
2017-07-18 19:51



In Python 3, ist die Standardcodierung "utf-8", so können Sie direkt verwenden:

b'hello'.decode()

was entspricht

b'hello'.decode(encoding="utf-8")

Andererseits, in Python 2Standardmäßig werden für die Kodierung die Standardzeichenfolge verwendet. Daher sollten Sie Folgendes verwenden:

b'hello'.decode(encoding)

woher encoding ist die Kodierung, die Sie wollen.

Hinweis: Unterstützung für Schlüsselwortargumente wurde in Python 2.7 hinzugefügt.


30
2018-06-29 14:21



Setzen Sie universal_newlines auf True, d. H.

command_stdout = Popen(['ls', '-l'], stdout=PIPE, universal_newlines=True).communicate()[0]

26
2018-01-21 15:31



Während @Aaron Maenpaas Antwort funktioniert einfach, ein Benutzer vor kurzem gefragt

Gibt es einen einfacheren Weg? 'fhand.read () .decodieren ("ASCII")' [...] Es ist so lang!

Sie können verwenden

command_stdout.decode()

decode() hat ein Standardargument

codecs.decode(obj, encoding='utf-8', errors='strict')


15
2017-11-13 10:24