Konvertieren Sie Bytes in einen String in Python 3

Lesezeit: 7 Minuten

Benutzer-Avatar von Tomas Sedovic
Tomas Sedovic

Ich habe die Standardausgabe eines externen Programms in a erfasst bytes Objekt:

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>>
>>> 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 das in einen normalen Python-String umwandeln, damit ich ihn wie folgt 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

Wie konvertiere ich die bytes Einspruch gegen a str mit Python 3?


Siehe Beste Möglichkeit zum Konvertieren von Zeichenfolgen in Bytes in Python 3? für den umgekehrten Fall.

  • warum nicht str(text_bytes) arbeiten? Das kommt mir bizarr vor.

    – Charlie Parker

    14. März 2019 um 22:25 Uhr

  • @CharlieParker Weil str(text_bytes) Die Codierung kann nicht angegeben werden. Abhängig davon, was in text_bytes steht, text_bytes.decode('cp1250)` könnte zu einer ganz anderen Zeichenfolge führen als text_bytes.decode('utf-8').

    – Craig Anderson

    31. März 2019 um 17:32 Uhr


  • So str Funktion wird nicht mehr in einen echten String konvertiert. Aus irgendeinem Grund MUSS man explizit eine Codierung sagen. Ich bin zu faul, um zu lesen, warum. Konvertieren Sie es einfach in utf-8 und sehen Sie, ob Ihr Code funktioniert. z.B var = var.decode('utf-8')

    – Charlie Parker

    22. April 2019 um 23:32 Uhr


  • @CraigAnderson: unicode_text = str(bytestring, character_encoding) Funktioniert jedoch wie erwartet unter Python 3 unicode_text = bytestring.decode(character_encoding) ist vorzuziehen, um Verwechslungen mit just zu vermeiden str(bytes_obj) das erzeugt eine Textdarstellung für bytes_obj Anstatt es in Text zu dekodieren: str(b'\xb6', 'cp1252') == b'\xb6'.decode('cp1252') == '¶' Und str(b'\xb6') == "b'\\xb6'" == repr(b'\xb6') != '¶'

    – jfs

    12. April 2020 um 5:11 Uhr

  • Sie können auch bestehen text=True Zu subprocess.run() oder .Popen() und dann erhalten Sie eine Zeichenfolge zurück, ohne dass Bytes konvertiert werden müssen. Oder angeben encoding="utf-8" zu einer der beiden Funktionen.

    – David Gilbertson

    13. September 2022 um 5:46 Uhr

Aaron Maenpaas Benutzeravatar
Aaron Maenpaa

Entschlüsseln Sie die bytes Objekt um eine Zeichenfolge zu erzeugen:

>>> b"abcde".decode("utf-8") 
'abcde'

Das obige Beispiel geht davon aus dass die bytes Das Objekt ist in UTF-8, da es sich um eine gängige Kodierung handelt. Sie sollten jedoch die Codierung verwenden, in der sich Ihre Daten tatsächlich befinden!

  • Ja, aber da dies die Ausgabe eines Windows-Befehls ist, sollte stattdessen nicht „.decode(‘windows-1252’)“ verwendet werden?

    – mcherm

    18. Juli 2011 um 19:48

  • Benutzen "windows-1252" auch nicht zuverlässig ist (z. B. für andere Sprachversionen von Windows), wäre es nicht das Beste, es zu verwenden sys.stdout.encoding?

    – nikow

    3. Januar 2012 um 15:20

  • Vielleicht hilft das jemandem weiter: Manchmal verwenden Sie Byte-Arrays für die TCP-Kommunikation. Wenn Sie ein Byte-Array in eine Zeichenfolge umwandeln möchten, indem Sie nachgestellte „\x00“-Zeichen abschneiden, reicht die folgende Antwort nicht aus. Verwenden Sie dann b’example\x00\x00′.decode(‘utf-8’).strip(‘\x00’).

    – Wookie88

    16. April 2013 um 13:27 Uhr

  • Offizielle Dokumentation dazu: für alle bytes Und bytearray Operationen (Methoden, die auf diesen Objekten aufgerufen werden können), siehe hier: docs.python.org/3/library/stdtypes.html#bytes-methods. Für bytes.decode() insbesondere siehe hier: docs.python.org/3/library/stdtypes.html#bytes.decode.

    – Gabriel Staples

    25. März 2021 um 4:12


Benutzeravatar von dF
dF.

Dekodieren Sie die Bytezeichenfolge und wandeln Sie sie in eine Zeichenzeichenfolge (Unicode) um.


Python 3:

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

oder

str(b'hello', encoding)

Python 2:

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

oder

unicode('hello', encoding)

Sissos Benutzeravatar
Sisso

Dadurch wird eine Liste von Bytes zu einer Zeichenfolge zusammengefügt:

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

  • @leetNightshade: Dennoch ist es furchtbar ineffizient. Wenn Sie ein Byte-Array haben, müssen Sie es nur dekodieren.

    – Martijn Pieters

    1. September 2014 um 16:25

  • @Sasszem: Diese Methode ist eine perverse Art auszudrücken: a.decode('latin-1') Wo a = bytearray([112, 52, 52]) („Es gibt keinen Klartext“. Wenn Sie es geschafft haben, Bytes in eine Textzeichenfolge umzuwandeln, haben Sie eine Codierung verwendet –latin-1 in diesem Fall)

    – jfs

    16. November 2016 um 3:16

  • @leetNightshade: Der Vollständigkeit halber: bytes(list_of_integers).decode('ascii') ist etwa 1/3 schneller als ''.join(map(chr, list_of_integers)) auf Python 3.6.

    – Martijn Pieters

    3. Juli 2018 um 12:01 Uhr


Benutzeravatar von anatoly techtonik
anatoli techtonik

Wenn Sie die Codierung nicht kennen, verwenden Sie das alte MS-DOS, um binäre Eingaben auf eine mit Python 3 und Python 2 kompatible Weise in einen String einzulesen 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, müssen Sie damit rechnen, dass nicht-englische Symbole in Zeichen von übersetzt werden cp437 (Englische Zeichen werden nicht übersetzt, da sie in den meisten Einzelbyte-Kodierungen und UTF-8 übereinstimmen).

Das Dekodieren beliebiger Binäreingaben in UTF-8 ist unsicher, da Sie möglicherweise Folgendes erhalten:

>>> 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-1was für Python 2 beliebt war (die Standardeinstellung?). Siehe die fehlenden Punkte in Codepage-Layout – Hier erstickt Python vor Berüchtigtheit ordinal not in range.

UPDATE 20150604: Es gibt Gerüchte, dass Python 3 das hat surrogateescape Fehlerstrategie zum Codieren von Inhalten in Binärdaten ohne Datenverlust und Abstürze, aber es sind Konvertierungstests erforderlich. [binary] -> [str] -> [binary]um sowohl Leistung als auch Zuverlässigkeit zu validieren.

UPDATE 20170116: Dank des Kommentars von Nearoo gibt es auch die Möglichkeit, alle unbekannten Bytes mit einem Slash-Escape zu versehen backslashreplace Fehlerbehandler. Das funktioniert nur für Python 3, sodass Sie selbst mit dieser Problemumgehung immer noch inkonsistente Ausgaben verschiedener Python-Versionen erhalten:

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 Pythons Unicode-Unterstützung für Details.

UPDATE 20170119: Ich habe beschlossen, Slash-Escape-Dekodierung zu implementieren, die sowohl für Python 2 als auch für Python 3 funktioniert. Sie sollte langsamer sein als die 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'))

Benutzeravatar von lmiguelvargasf
lmiguelvargasf

In Python 3die Standardkodierung ist "utf-8"sodass Sie Folgendes direkt verwenden können:

b'hello'.decode()

was gleichbedeutend mit ist

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

Andererseits, in Python 2Die Codierung erfolgt standardmäßig auf die Standard-String-Codierung. Daher sollten Sie Folgendes verwenden:

b'hello'.decode(encoding)

Wo encoding ist die gewünschte Codierung.

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

Benutzer-Avatar von Peter Mortensen
Peter Mortensen

Ich denke, dass du das tatsächlich willst:

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

Aarons Antwort war richtig, außer dass Sie es wissen müssen welche zu verwendende Kodierung. Und ich glaube, dass Windows „Windows-1252“ verwendet. Es spielt nur dann eine Rolle, wenn Ihr Inhalt ungewöhnliche Zeichen (nicht ASCII) enthält, aber dann macht es einen Unterschied.

Übrigens, die Tatsache, dass es tut Materie ist der Grund dafür, dass Python dazu übergegangen ist, zwei verschiedene Typen für Binär- und Textdaten zu verwenden: Es kann nicht auf magische Weise zwischen ihnen konvertieren, weil es die Codierung nicht kennt, es sei denn, Sie sagen es ihm! Die einzige Möglichkeit, die Sie wissen würden, besteht darin, die Windows-Dokumentation zu lesen (oder sie hier zu lesen).

Da es sich bei dieser Frage eigentlich um eine Frage handelt subprocess Ausgabe stehen Ihnen mehr direkte Ansätze zur Verfügung. Am modernsten wäre die Nutzung subprocess.check_output und vorbei text=True (Python 3.7+) zum automatischen Dekodieren von stdout unter Verwendung der Systemstandardkodierung:

text = subprocess.check_output(["ls", "-l"], text=True)

Für Python 3.6, Popen akzeptiert eine Codierung Stichwort:

>>> from subprocess import Popen, PIPE
>>> text = Popen(['ls', '-l'], stdout=PIPE, encoding='utf-8').communicate()[0]
>>> type(text)
str
>>> print(text)
total 0
-rw-r--r-- 1 wim badger 0 May 31 12:45 some_file.txt

Wenn Sie sich nicht mit der Ausgabe von Unterprozessen befassen, lautet die allgemeine Antwort auf die Frage im Titel: dekodieren Bytes zum Text:

>>> b'abcde'.decode()
'abcde'

Ohne Argument, sys.getdefaultencoding() verwendet wird. Wenn Ihre Daten nicht vorhanden sind sys.getdefaultencoding()dann müssen Sie die Kodierung explizit im angeben decode Forderung:

>>> b'caf\xe9'.decode('cp1250')
'café'

1454730cookie-checkKonvertieren Sie Bytes in einen String in Python 3

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy