web-dev-qa-db-fra.com

Que fait le caractère 'b' devant un littéral de chaîne?

Apparemment, ce qui suit est une syntaxe valide

my_string = b'The string'

J'aimerais savoir:

  1. Que signifie ce caractère b devant la chaîne?
  2. Quels sont les effets de l'utiliser?
  3. Quelles sont les situations appropriées pour l'utiliser?

J'ai trouvé un question connexe ici même sur SO, mais cette question concerne PHP cependant, et indique que la b est utilisée pour indiquer que la chaîne est binaire, contrairement à Unicode, qui était nécessaire pour que le code soit compatible à partir de la version de PHP <6, lors de la migration vers PHP 6. Je ne pense pas que cela s'applique à Python.

J'ai trouvé cette documentation sur le site Python concernant l'utilisation d'un caractère u dans la même syntaxe pour spécifier une chaîne au format Unicode. Malheureusement, le caractère b ne figure nulle part dans ce document.

Aussi, juste par curiosité, y a-t-il plus de symboles que les b et u qui font autre chose?

668
Jesse Webb

Pour citer la documentation Python 2.x :

Un préfixe 'b' ou 'B' est ignoré dans Python 2; il indique que le littéral doit devenir un littéral d'octets dans Python 3 (par exemple, lorsque le code est automatiquement converti avec 2to3). Un préfixe "u" ou "b" peut être suivi d'un préfixe "r".

Le documentation Python indique:

Les littéraux d'octets sont toujours précédés de 'b' ou 'B'; ils produisent une instance du type octets au lieu du type str. Ils ne peuvent contenir que ASCII caractères; les octets avec une valeur numérique de 128 ou plus doivent être exprimés avec des échappements.

339
NPE

Python 3.x distingue clairement les types:

  • str = '...' littéraux = une séquence de caractères Unicode (UTF-16 ou UTF-32, selon la manière dont Python a été compilé)
  • bytes = b'...' littéraux = une séquence d'octets (entiers compris entre 0 et 255)

Si vous connaissez Java ou C #, considérez str comme String et bytes comme byte[]. Si vous connaissez SQL, considérez str comme NVARCHAR et bytes comme BINARY ou BLOB. Si vous connaissez le registre Windows, imaginez str comme REG_SZ et bytes comme REG_BINARY. Si vous connaissez C (++), oubliez tout ce que vous avez appris sur char et les chaînes, car UN CARACTÈRE IS PAS UN BYTE . Cette idée est obsolète depuis longtemps.

Vous utilisez str lorsque vous souhaitez représenter du texte.

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

Vous utilisez bytes lorsque vous souhaitez représenter des données binaires de bas niveau, telles que des structures.

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

Vous pouvez encoder un str en un objet bytes.

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

Et vous pouvez décoder une bytes en str.

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

Mais vous ne pouvez pas mélanger librement les deux types.

>>> 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

La notation b'...' est quelque peu déroutante dans la mesure où elle permet de spécifier les octets 0x01-0x7F avec des caractères ASCII au lieu de nombres hexadécimaux.

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

Mais je dois souligner, qu'un caractère n'est pas un octet .

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

Dans Python 2.x

Les versions antérieures à la version 3.0 de Python ne présentaient pas ce type de distinction entre le texte et les données binaires. Au lieu de cela, il y avait:

  • unicode = u'...' littéraux = séquence de caractères Unicode = 3.x str
  • str = '...' littéraux = séquences d'octets/caractères confondus
    • Généralement du texte, codé dans un codage non spécifié.
    • Mais aussi utilisé pour représenter des données binaires comme struct.pack output.

Afin de faciliter la transition de 2.x à 3.x, la syntaxe littérale b'...' a été reportée sur Python 2.6, afin de permettre la distinction des chaînes binaires (qui devrait être bytes dans 3.x) à partir de chaînes de texte (qui devrait être str dans 3.x). Le préfixe b ne fait rien dans la version 2.x, mais indique au script 2to3 de ne pas le convertir en chaîne Unicode en 3.x.

Alors oui, b'...' les littéraux de Python ont le même objectif que ceux de PHP.

Aussi, juste par curiosité, y a-t-il plus de symboles que le b et u qui font autre chose?

Le préfixe r crée une chaîne brute (par exemple, r'\t' est une barre oblique inverse + t au lieu d'un onglet), et des guillemets triples '''...''' ou """...""" permettent plusieurs -lignes de chaînes de caractères.

560
dan04

Le b indique une chaîne d'octets.

Les octets sont les données réelles. Les chaînes sont une abstraction.

Si vous aviez un objet chaîne à plusieurs caractères et que vous preniez un seul caractère, il s'agirait d'une chaîne, dont la taille pourrait être supérieure à 1 octet, en fonction de l'encodage.

Si vous prenez 1 octet avec une chaîne d'octets, vous obtiendrez une valeur unique de 8 bits comprise entre 0 et 255 et il se peut que ce dernier ne représente pas un caractère complet si ces caractères dus au codage étaient supérieurs à 1 octet.

TBH J'utilisais des chaînes sauf si j'avais une raison particulière d'utiliser des octets.

16
gecko

Du côté du serveur, si nous envoyons une réponse, elle sera envoyée sous la forme de type octet, elle apparaîtra donc dans le client sous la forme b'Response from server'

Pour vous débarrasser de b'....', utilisez simplement le code ci-dessous:

Fichier serveur:

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

Dossier client:

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

alors il imprimera Response from server

9
Nani Chintha

Il le transforme en un littéral bytes (ou str dans 2.x) et est valide à partir de la version 2.6.

Le préfixe r fait en sorte que les barres obliques inverses soient "non interprétées" (pas ignorées, et la différence fait importe).

Voici un exemple où l'absence de b lève une exception TypeError dans Python 3.x

>>> 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

Ajouter un préfixe b résoudrait le problème.

8
user3053230

Outre ce que d'autres ont dit, notez qu'un seul caractère en unicode peut être composé de plusieurs octets .

Le fonctionnement de l’unicode est qu’il reprenait l’ancien format ASCII (code 7 bits ressemblant à 0xxx xxxx) et ajoutait séquences multi-octets où tous les octets commencent par 1 (1xxx). xxxx) pour représenter des caractères au-delà de ASCII afin que Unicode soit rétrocompatible avec 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
2
xjcl

Vous pouvez utiliser JSON pour le convertir en dictionnaire

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

{"valeur clé"}


BALLON:

Ceci est un exemple de flask. Exécutez ceci sur la ligne de terminal:

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

En fiole/routes.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)

{'valeur clé'}

0
Karam Qusai