Ich verwende diesen Code, um die Standardausgabe eines externen Programms zu erhalten:
>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
Die Methode communic () 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 normaler Python-String 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, dafür ist die binascii.b2a_qp () -Methode gedacht , aber als ich es versuchte, bekam ich wieder das gleiche Byte-Array:
>>> 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'
Wie konvertiere ich den Bytewert zurück in einen String? Ich meine, die "Batterien" zu verwenden, anstatt es manuell zu tun. Und ich möchte, dass Python 3 in Ordnung ist.
python
string
python-3.x
Tomas Sedovic
quelle
quelle
str(text_bytes)
funktioniert? Das kommt mir bizarr vor.str(text_bytes)
die Codierung nicht angegeben werden kann. Abhängig davon, was in text_bytes enthalten ist, kanntext_bytes.decode('cp1250
) `zu einer ganz anderen Zeichenfolge führen alstext_bytes.decode('utf-8')
.str
Funktion wird also nicht mehr in eine echte Zeichenfolge konvertiert. Man muss aus irgendeinem Grund explizit eine Kodierung sagen. Ich bin zu faul, um durchzulesen, warum. Konvertieren Sie es einfach inutf-8
und prüfen Sie, ob Ihr Code funktioniert. zBvar = var.decode('utf-8')
unicode_text = str(bytestring, character_encoding)
wie erwartet unter Python 3. Esunicode_text = bytestring.decode(character_encoding)
ist jedoch vorzuziehen, Verwechslungen zu vermeiden, da nurstr(bytes_obj)
eine Textdarstellung erstellt wird,bytes_obj
anstatt sie in Text zu dekodieren:str(b'\xb6', 'cp1252') == b'\xb6'.decode('cp1252') == '¶'
undstr(b'\xb6') == "b'\\xb6'" == repr(b'\xb6') != '¶'
Antworten:
Sie müssen das Byte-Objekt dekodieren, um eine Zeichenfolge zu erstellen:
quelle
"windows-1252"
ist auch nicht zuverlässig (z. B. für andere Sprachversionen von Windows). Wäre die Verwendung nicht am bestensys.stdout.encoding
?b"\x80\x02\x03".decode("utf-8")
->UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: invalid start byte
.utf-8
Konvertierung wahrscheinlich fehl. Siehe @techtonik Antwort (unten) stackoverflow.com/a/27527728/198536Sie müssen die Byte-Zeichenfolge dekodieren und in eine Zeichenfolge (Unicode) umwandeln.
Auf Python 2
oder
Auf Python 3
oder
quelle
variable = b'hello'
unicode_text = variable.decode(character_encoding)
Ich denke, dieser Weg ist einfach:
quelle
bytes([112, 52, 52])
- Übrigens ist Bytes ein schlechter Name für eine lokale Variable, genau weil es sich um eine integrierte p3 handeltWenn Sie die Codierung nicht kennen, verwenden Sie die alte MS-DOS CP437- Codierung , um binäre Eingaben in Zeichenfolgen in Python 3- und Python 2-kompatibler Weise zu lesen :
Da die Codierung unbekannt ist, erwarten Sie, dass nicht englische Symbole in Zeichen von übersetzt werden
cp437
(englische Zeichen werden nicht übersetzt, da sie in den meisten Einzelbyte-Codierungen und UTF-8 übereinstimmen).Das Dekodieren eines beliebigen Binäreingangs in UTF-8 ist unsicher, da dies möglicherweise auftritt:
Gleiches gilt für das
latin-1
, was für Python 2 beliebt war (Standardeinstellung?). Siehe die fehlenden Punkte im Codepage-Layout - hier erstickt Python mit berüchtigtenordinal not in range
.UPDATE 20150604 : Es gibt Gerüchte, dass Python 3 die
surrogateescape
Fehlerstrategie zum Codieren von Daten in Binärdaten ohne Datenverlust und Abstürze hat. Es sind jedoch Konvertierungstests erforderlich[binary] -> [str] -> [binary]
, um sowohl die Leistung als auch die Zuverlässigkeit zu überprüfen .UPDATE 20170116 : Dank des Kommentars von Nearoo besteht auch die Möglichkeit, alle unbekannten Bytes mit dem
backslashreplace
Fehlerhandler zu verkleinern. Dies funktioniert nur für Python 3, sodass Sie auch mit dieser Problemumgehung eine inkonsistente Ausgabe von verschiedenen Python-Versionen erhalten:Weitere Informationen finden Sie in der Unicode-Unterstützung von Python .
UPDATE 20170119 : Ich habe mich für die Implementierung einer Schrägstrich- Escape- Dekodierung entschieden, die sowohl für Python 2 als auch für Python 3 funktioniert. Sie sollte langsamer als die
cp437
Lösung sein, aber bei jeder Python-Version identische Ergebnisse liefern .quelle
b'\x00\x01\xffsd'.decode('utf-8', 'ignore')
in Python 3 einfach ignorieren .b'\x80abc'.decode("utf-8", "backslashreplace")
führt zu'\\x80abc'
. Diese Informationen stammen aus der Unicode-Dokumentationsseite, die seit dem Schreiben dieser Antwort aktualisiert worden zu sein scheint.In Python 3 lautet die Standardcodierung
"utf-8"
, sodass Sie direkt Folgendes verwenden können:das ist äquivalent zu
In Python 2 wird für die Codierung standardmäßig die Standard-Zeichenfolgencodierung verwendet. Daher sollten Sie verwenden:
Wo
encoding
ist die gewünschte Codierung?Hinweis: Die Unterstützung für Schlüsselwortargumente wurde in Python 2.7 hinzugefügt.
quelle
Ich denke du willst das wirklich:
Aarons Antwort war richtig, außer dass Sie wissen müssen, welche Codierung Sie verwenden sollen. Und ich glaube, dass Windows 'Windows-1252' verwendet. Es spielt nur eine Rolle, wenn Ihr Inhalt ungewöhnliche (Nicht-ASCII-) Zeichen enthält, aber dann macht es einen Unterschied.
By the way, die Tatsache , dass es tut Materie ist der Grund , dass Python mit zwei verschiedenen Typen für binäre und Textdaten verschoben: es magisch zwischen ihnen nicht konvertieren kann, weil es nicht die Kodierung nicht wissen , wenn Sie ihm sagen! Sie können nur die Windows-Dokumentation lesen (oder hier lesen).
quelle
open()
Funktion für Textströme oderPopen()
wenn Sie sie bestehenuniversal_newlines=True
, entscheiden Sie auf magische Weise über die Zeichenkodierung für Sie (locale.getpreferredencoding(False)
in Python 3.3+).'latin-1'
ist eine wörtliche Codierung, bei der alle Codepunkte festgelegt sind. Sie können diese also verwenden, um eine Byte-Zeichenfolge effektiv in den von Python unterstützten Zeichenfolgentyp einzulesen (also wörtlich in Python 2, in Unicode für Python 3).'latin-1'
ist ein guter Weg, um Mojibake zu bekommen. Es gibt auch magische Ersetzungen unter Windows: Es ist überraschend schwierig, Daten von einem Prozess zu einem anderen unverändert weiterzuleiten, z. Bdir
.:\xb6
->\x14
(das Beispiel am Ende meiner Antwort)Setzen Sie universal_newlines auf True, dh
quelle
text=True
stattdessen tununiversal_newlines=True
.Während die Antwort von @Aaron Maenpaa gerade funktioniert, hat ein Benutzer kürzlich gefragt :
Sie können verwenden:
decode()
hat ein Standardargument :quelle
.decode()
'utf-8'
Diese Verwendung kann fehlschlagen (die Ausgabe des Befehls verwendet möglicherweise eine andere Zeichenkodierung oder gibt sogar eine nicht dekodierbare Bytesequenz zurück). Wenn die Eingabe jedoch ascii ist (eine Teilmenge von utf-8),.decode()
funktioniert dies.Um eine Bytefolge als Text zu interpretieren, müssen Sie die entsprechende Zeichenkodierung kennen:
Beispiel:
ls
Der Befehl kann eine Ausgabe erzeugen, die nicht als Text interpretiert werden kann. Dateinamen unter Unix können eine beliebige Folge von Bytes sein, außer Schrägstrichb'/'
und Nullb'\0'
:Der Versuch, eine solche Bytesuppe mit utf-8-Codierungserhöhungen zu dekodieren
UnicodeDecodeError
.Es kann schlimmer sein. Die Dekodierung schlägt möglicherweise stillschweigend fehl und erzeugt Mojibake, wenn Sie eine falsche inkompatible Codierung verwenden:
Die Daten sind beschädigt, aber Ihr Programm weiß nicht, dass ein Fehler aufgetreten ist.
Im Allgemeinen ist die zu verwendende Zeichenkodierung nicht in die Bytesequenz selbst eingebettet. Sie müssen diese Informationen außerhalb des Bandes kommunizieren. Einige Ergebnisse sind wahrscheinlicher als andere, und daher gibt es ein
chardet
Modul, das die Zeichenkodierung erraten kann . Ein einzelnes Python-Skript kann mehrere Zeichencodierungen an verschiedenen Stellen verwenden.ls
Ausgabe kann an eine Python Zeichenfolge umgewandelt werden unter Verwendung vonos.fsdecode()
Funktion , die auch für gelingt es nicht decodierbaren Dateinamen (es verwendetsys.getfilesystemencoding()
undsurrogateescape
Fehler - Handler auf Unix):Um die ursprünglichen Bytes zu erhalten, können Sie verwenden
os.fsencode()
.Wenn Sie einen
universal_newlines=True
Parameter übergeben,subprocess
wird erlocale.getpreferredencoding(False)
zum Dekodieren von Bytes verwendet, z. B. untercp1252
Windows.Um den Byte-Stream im laufenden Betrieb zu dekodieren,
io.TextIOWrapper()
könnte Folgendes verwendet werden: Beispiel .Unterschiedliche Befehle können unterschiedliche Zeichencodierungen für ihre Ausgabe verwenden, z. B. kann
dir
interner Befehl (cmd
) cp437 verwenden. Um die Ausgabe zu dekodieren, können Sie die Codierung explizit übergeben (Python 3.6+):Die Dateinamen können von
os.listdir()
denen abweichen (die die Windows-Unicode-API verwenden), z. B.'\xb6'
können sie durch'\x14'
die cp437-Codec-Zuordnungen von Python ersetzt werdenb'\x14'
, um das Zeichen U + 0014 anstelle von U + 00B6 (¶) zu steuern. Informationen zur Unterstützung von Dateinamen mit beliebigen Unicode-Zeichen finden Sie unter Decodieren der PowerShell-Ausgabe, die möglicherweise Nicht-ASCII-Unicode-Zeichen enthält, in eine Python-Zeichenfolgequelle
Da diese Frage tatsächlich die
subprocess
Ausgabe betrifft , steht Ihnen ein direkterer Ansatz zur Verfügung, daPopen
ein Codierungsschlüsselwort (in Python 3.6+) akzeptiert wird :Die allgemeine Antwort für andere Benutzer besteht darin , Bytes in Text zu dekodieren :
Ohne Argument
sys.getdefaultencoding()
wird verwendet. Wenn Ihre Daten nicht vorhanden sindsys.getdefaultencoding()
, müssen Sie die Codierung imdecode
Aufruf explizit angeben :quelle
text=True
stdin, stdout und stderr mit der angegebenen Codierung (falls festgelegt) oder dem anderen Systemstandard dekodieren.Popen(['ls', '-l'], stdout=PIPE, text=True)
.ls
Ausgabe mithilfe derutf-8
Codierung schlägt möglicherweise fehl (siehe Beispiel in meiner Antwort von 2016 ).encoding
Parameter angegeben wird, wird dertext
Parameter ignoriert.Wenn Sie Folgendes versuchen sollten
decode()
:Sie können den Codierungstyp auch direkt in einer Besetzung angeben:
quelle
Wenn
\r\n
ich mit Daten von Windows-Systemen (mit Zeilenenden) arbeite , lautet meine AntwortWarum? Versuchen Sie dies mit einer mehrzeiligen Input.txt:
Alle Ihre Zeilenenden werden verdoppelt (bis
\r\r\n
), was zu zusätzlichen leeren Zeilen führt. Die Textlesefunktionen von Python normalisieren normalerweise Zeilenenden, sodass nur Zeichenfolgen verwendet werden\n
. Wenn Sie Binärdaten von einem Windows-System empfangen, hat Python keine Möglichkeit dazu. Somit,repliziert Ihre Originaldatei.
quelle
.replace("\r\n", "\n")
so lange nach einem Zusatz gesucht . Dies ist die Antwort, wenn Sie HTML richtig rendern möchten.Ich habe eine Funktion zum Bereinigen einer Liste erstellt
quelle
.strip
,.replace
,.encode
usw. Anrufe in einer Liste Verständnis und Iterierte nur über die Liste einmal statt Iterieren über fünfmal.Für Python 3 ist dies ein viel sicherer und Pythonic Ansatz zur Umwandlung von
byte
zustring
:Ausgabe:
quelle
byte_to_str
", was bedeutet, dass sie einen str zurückgibt, aber nur den konvertierten Wert ausgibt und eine Fehlermeldung ausgibt, wenn dies fehlschlägt (aber keine Ausnahme auslöst). Dieser Ansatz ist auch unpythonisch und verschleiert die vonbytes.decode
Ihnen bereitgestellte Lösung.Von sys - Systemspezifische Parameter und Funktionen :
Verwenden Sie den zugrunde liegenden Binärpuffer, um Binärdaten von / in die Standard-Streams zu schreiben oder zu lesen. Verwenden Sie beispielsweise, um Bytes in stdout zu schreiben
sys.stdout.buffer.write(b'abc')
.quelle
bytes
Wert ein Zeichenfolgenwert abgerufen werden kann.quelle
Für Ihren speziellen Fall "Führen Sie einen Shell-Befehl aus und erhalten Sie seine Ausgabe als Text anstelle von Bytes" sollten Sie in Python 3.7 verwenden
subprocess.run
und übergebentext=True
(sowiecapture_output=True
die Ausgabe erfassen).text
wurde früher aufgerufenuniversal_newlines
und in Python 3.7 geändert (naja, alias). Wenn Sie Python-Versionen vor 3.7 unterstützen möchten, übergeben Sieuniversal_newlines=True
statttext=True
quelle
Wenn Sie Bytes konvertieren möchten, konvertieren Sie nicht nur Zeichenfolgen in Bytes:
Dies ist jedoch nicht sehr effizient. Aus einem 2-MB-Bild werden 9 MB.
quelle
Versuche dies
quelle