Was macht das 'b'-Zeichen vor einem String-Literal?

831

Anscheinend ist das Folgende die gültige Syntax:

my_string = b'The string'

Ich würde gerne wissen:

  1. Was bedeutet dieses bZeichen vor der Zeichenfolge?
  2. Welche Auswirkungen hat die Verwendung?
  3. Was sind geeignete Situationen, um es zu verwenden?

Ich habe hier auf SO eine verwandte Frage gefunden, aber diese Frage bezieht sich auf PHP und besagt b, dass die Zeichenfolge binär ist, im Gegensatz zu Unicode, das benötigt wurde, damit Code mit der Version von PHP <6 kompatibel ist Ich glaube nicht, dass dies für Python gilt, wenn Sie auf PHP 6 migrieren.

Ich habe diese Dokumentation auf der Python-Site über die Verwendung eines uZeichens in derselben Syntax gefunden, um eine Zeichenfolge als Unicode anzugeben. Leider wird das b- Zeichen nirgendwo in diesem Dokument erwähnt.

Gibt es aus Neugier mehr Symbole als die bund udie andere Dinge tun?

Jesse Webb
quelle

Antworten:

416

So zitieren Sie die Python 2.x-Dokumentation :

Ein Präfix von 'b' oder 'B' wird in Python 2 ignoriert. Es gibt an, dass das Literal in Python 3 zu einem Byte-Literal werden soll (z. B. wenn Code automatisch mit 2to3 konvertiert wird). Auf ein Präfix 'u' oder 'b' kann ein Präfix 'r' folgen.

In der Python 3-Dokumentation heißt es:

Byte-Literalen wird immer 'b' oder 'B' vorangestellt. Sie erzeugen eine Instanz vom Typ Bytes anstelle des Typs str. Sie dürfen nur ASCII-Zeichen enthalten. Bytes mit einem numerischen Wert von 128 oder höher müssen mit Escapezeichen ausgedrückt werden.

NPE
quelle
4
Es hört sich also so an, als würde Python <v3 dieses zusätzliche Zeichen einfach ignorieren. Was wäre ein Fall in Version 3, in dem Sie eine ab-Zeichenfolge anstelle einer normalen Zeichenfolge verwenden müssten?
Jesse Webb
5
@Gweebz - wenn Sie tatsächlich eine Zeichenfolge in einer bestimmten Codierung anstelle von Unicode-Escapezeichen eingeben (z. B. b '\ xff \ xfe \ xe12' anstelle von '\ u32e1').
Detly
7
Eigentlich, wenn Sie importiert haben unicode_literalsaus __future__, wird diese „reverse“ das Verhalten für diese bestimmte Zeichenfolge (in Python 2.x)
Romuald Brunet
34
Eine etwas einfachere Erzählung um die zitierte Dokumentation würde dies meiner Meinung nach zu einer besseren Antwort machen
Hack-R
2
Ansonsten ist eine Antwort für jemanden, der es bereits versteht.
Rafael Eyng
680

Python 3.x unterscheidet klar zwischen den Typen:

  • str= '...'Literale = eine Folge von Unicode-Zeichen (UTF-16 oder UTF-32, je nachdem, wie Python kompiliert wurde)
  • bytes= b'...'Literale = eine Folge von Oktetten (ganze Zahlen zwischen 0 und 255)

Wenn Sie mit Java oder C # vertraut sind, denken Sie an stras Stringund bytesas byte[]. Wenn Sie mit SQL vertraut sind, denken Sie an stras NVARCHARund bytesas BINARYoder BLOB. Wenn Sie mit der Windows-Registrierung vertraut sind, denken Sie an stras REG_SZund bytesas REG_BINARY. Wenn Sie mit C (++) vertraut sind, vergessen Sie alles, was Sie gelernt haben, charund Zeichenfolgen, da ein Zeichen kein Byte ist . Diese Idee ist längst überholt.

Sie verwenden, strwenn Sie Text darstellen möchten.

print('שלום עולם')

Sie werden verwendet, byteswenn Sie binäre Daten auf niedriger Ebene wie Strukturen darstellen möchten.

NaN = struct.unpack('>d', b'\xff\xf8\x00\x00\x00\x00\x00\x00')[0]

Sie können a in ein Objekt codieren .strbytes

>>> '\uFEFF'.encode('UTF-8')
b'\xef\xbb\xbf'

Und Sie können a bytesin a dekodieren str.

>>> b'\xE2\x82\xAC'.decode('UTF-8')
'€'

Sie können die beiden Typen jedoch nicht frei mischen.

>>> b'\xEF\xBB\xBF' + 'Text with a UTF-8 BOM'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat bytes to str

Die b'...'Notation ist insofern etwas verwirrend, als die Bytes 0x01-0x7F mit ASCII-Zeichen anstelle von Hex-Zahlen angegeben werden können.

>>> b'A' == b'\x41'
True

Aber ich muss betonen, ein Zeichen ist kein Byte .

>>> 'A' == b'A'
False

In Python 2.x.

In Versionen vor 3.0 von Python fehlte diese Unterscheidung zwischen Text und Binärdaten. Stattdessen gab es:

  • unicode= u'...'Literale = Folge von Unicode-Zeichen = 3.x.str
  • str= '...'Literale = Folgen von verwirrten Bytes / Zeichen
    • Normalerweise Text, der in einer nicht spezifizierten Codierung codiert ist.
    • Wird aber auch zur Darstellung von Binärdaten wie struct.packAusgabe verwendet.

Um den Übergang von 2.x zu 3.x zu vereinfachen, wurde die b'...'Literal-Syntax auf Python 2.6 zurückportiert, um die Unterscheidung von Binärzeichenfolgen (die bytesin 3.x sein sollten) von Textzeichenfolgen (die strin 3 sein sollten) zu ermöglichen .x). Das bPräfix führt in 2.x nichts aus, weist das 2to3Skript jedoch an, es in 3.x nicht in eine Unicode-Zeichenfolge zu konvertieren.

Also ja, b'...'Literale in Python haben den gleichen Zweck wie in PHP.

Gibt es aus Neugier mehr Symbole als das b und u, die andere Dinge tun?

Das rPräfix erstellt eine unformatierte Zeichenfolge (z. B. r'\t'ein Backslash + tanstelle einer Registerkarte) und dreifache Anführungszeichen '''...'''oder """..."""lässt mehrzeilige Zeichenfolgenliterale zu.

dan04
quelle
2
Vielen Dank! Nachdem ich diese Sätze gelesen hatte, verstand ich es: "Um den Übergang von 2.x zu 3.x zu vereinfachen, wurde die wörtliche Syntax b '...' auf Python 2.6 zurückportiert, um die Unterscheidung von Binärzeichenfolgen zu ermöglichen (was sollte) Be Bytes in 3.x) aus Textzeichenfolgen (die in 3.x str sein sollten). Das Präfix b bewirkt in 2.x nichts, weist das 2to3-Skript jedoch an, es in 3.x nicht in eine Unicode-Zeichenfolge zu konvertieren. "
Tommy.carstensen
4
Der 'A' == b'A' --> FalseScheck macht es wirklich klar. Der Rest ist ausgezeichnet, aber bis zu diesem Punkt hatte ich nicht richtig verstanden, dass eine Byte-Zeichenfolge nicht wirklich Text ist.
Wildcard
12
'שלום עולם' == 'hello world'
Eli
12
Dies ist viel klarer als die akzeptierte Antwort, die nur die Dokumentation zitiert. Die Dokumentation hat für mich keinen Sinn ergeben, daher ist es fantastisch, weiteren Kontext in der Dokumentation bereitzustellen. Vielen Dank!
Rayryeng
2
b "some string" .decode ('UTF-8'), ich glaube, das ist die Zeile, nach der viele suchen
Marvin Thobejane
22

Das b bezeichnet eine Bytezeichenfolge.

Bytes sind die tatsächlichen Daten. Strings sind eine Abstraktion.

Wenn Sie ein mehrstelliges Zeichenfolgenobjekt hätten und ein einzelnes Zeichen verwenden würden, wäre dies eine Zeichenfolge, die je nach Codierung mehr als 1 Byte groß sein könnte.

Wenn Sie 1 Byte mit einer Byte-Zeichenfolge belegen, erhalten Sie einen einzelnen 8-Bit-Wert von 0 bis 255, der möglicherweise kein vollständiges Zeichen darstellt, wenn diese Zeichen aufgrund der Codierung> 1 Byte sind.

TBH Ich würde Zeichenfolgen verwenden, es sei denn, ich hätte einen bestimmten Grund für die Verwendung von Bytes auf niedriger Ebene.


quelle
16

Wenn wir auf der Serverseite eine Antwort senden, wird diese in Form eines Bytetyps gesendet, sodass sie im Client als angezeigt wird b'Response from server'

Um loszuwerden, verwenden Sie b'....'einfach den folgenden Code:

Serverdatei:

stri="Response from server"    
c.send(stri.encode())

Client-Datei:

print(s.recv(1024).decode())

dann wird es gedruckt Response from server

Nani Chintha
quelle
1
Es erklärt nicht die Frage, die Jesse Webb gestellt hat!
Chandra Kanth
Ich sagte, dass ohne Verwendung von Codierungs- und Decodierungsmethoden der Zeichenfolgenausgabe b '' vorangestellt wird, da Python sie als Bytetyp anstelle des Zeichenfolgentyps verwendet. Wenn Sie keine Ausgabe wie b 'erhalten möchten ... Verwenden Sie das Obige, das ist es. Was Sie nicht verstanden haben?
Nani Chintha
Eigentlich ist dies genau die Antwort auf den Titel der gestellten Frage: F: "Was macht b'x '?" A: "Es macht 'x'.encode ()" Das ist buchstäblich das, was es macht. Der Rest der Frage wollte viel mehr als das wissen, aber der Titel wird beantwortet.
Michael Erickson
10

Hier ist ein Beispiel, bei dem das Fehlen von beine TypeErrorAusnahme in Python 3.x auslösen würde

>>> f=open("new", "wb")
>>> f.write("Hello Python!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' does not support the buffer interface

Das Hinzufügen eines bPräfixes würde das Problem beheben.

user3053230
quelle
9

Es verwandelt es in ein bytesLiteral (oder strin 2.x) und gilt für 2.6+.

Das rPräfix bewirkt, dass Backslashes "nicht interpretiert" werden (nicht ignoriert, und der Unterschied spielt eine Rolle).

Ignacio Vazquez-Abrams
quelle
Dies klingt gemäß der in der Antwort von aix zitierten Dokumentation falsch. Das b wird in einer anderen Python-Version als 3 ignoriert.
Jesse Webb
2
Es wird strin beiden Fällen ein in 2.x sein, also könnte man sagen, dass es ignoriert wird. Die Unterscheidung ist wichtig, wenn Sie unicode_literalsaus dem __future__Modul importieren .
Ignacio Vazquez-Abrams
6

Beachten Sie zusätzlich zu den Aussagen anderer, dass ein einzelnes Zeichen in Unicode aus mehreren Bytes bestehen kann .

Die Funktionsweise von Unicode besteht darin, dass das alte ASCII-Format (7-Bit-Code, der wie 0xxx xxxx aussieht) verwendet und Mehrbyte -Sequenzen hinzugefügt wurden , bei denen alle Bytes mit 1 (1xxx xxxx) beginnen, um Zeichen jenseits von ASCII darzustellen, sodass Unicode rückwärts ist -kompatibel mit ASCII.

>>> len('Öl')  # German word for 'oil' with 2 characters
2
>>> 'Öl'.encode('UTF-8')  # convert str to bytes 
b'\xc3\x96l'
>>> len('Öl'.encode('UTF-8'))  # 3 bytes encode 2 characters !
3
xjcl
quelle
2

Sie können JSON verwenden, um es in ein Wörterbuch zu konvertieren

import json
data = b'{"key":"value"}'
print(json.loads(data))

{"Schlüsselwert"}


FLASCHE:

Dies ist ein Beispiel aus der Flasche. Führen Sie dies auf der Terminalleitung aus:

import requests
requests.post(url='http://localhost(example)/',json={'key':'value'})

In flask / route.py

@app.route('/', methods=['POST'])
def api_script_add():
    print(request.data) # --> b'{"hi":"Hello"}'
    print(json.loads(request.data))
return json.loads(request.data)

{'Schlüsselwert'}

Karam Qusai
quelle