Question Meilleur moyen de convertir des chaînes en octets dans Python 3?


Il semble y avoir deux manières différentes de convertir une chaîne en octets, comme le montrent les réponses à TypeError: 'str' ne supporte pas l'interface tampon

Laquelle de ces méthodes serait la meilleure ou la plus pythonique? Ou est-ce juste une question de préférence personnelle?

b = bytes(mystring, 'utf-8')

b = mystring.encode('utf-8')

429
2017-09-28 15:14


origine


Réponses:


Si vous regardez les documents pour bytes, il vous indique bytearray:

bytearray ([source [, encodage [, erreurs]]])

Renvoie un nouveau tableau d'octets. Le type bytearray est une séquence mutable d'entiers dans l'intervalle 0 <= x <256. Il a la plupart des méthodes habituelles de séquences mutables, décrites dans Mutable Sequence Types, ainsi que la plupart des méthodes que le type bytes, voir Octets et Byte Array Methods.

Le paramètre source facultatif peut être utilisé pour initialiser le tableau de différentes manières:

S'il s'agit d'une chaîne, vous devez également indiquer les paramètres d'encodage (et éventuellement des erreurs). bytearray () convertit ensuite la chaîne en octets à l'aide de str.encode ().

S'il s'agit d'un entier, le tableau aura cette taille et sera initialisé avec des octets nuls.

S'il s'agit d'un objet conforme à l'interface tampon, un tampon en lecture seule de l'objet sera utilisé pour initialiser le tableau d'octets.

Si c'est un itérable, il doit s'agir d'un itérable d'entiers dans l'intervalle 0 <= x <256, qui sont utilisés comme contenu initial du tableau.

Sans argument, un tableau de taille 0 est créé.

Alors bytes peut faire beaucoup plus que simplement encoder une chaîne. C'est Pythonic que cela vous permettrait d'appeler le constructeur avec n'importe quel type de paramètre source qui a du sens.

Pour encoder une chaîne, je pense que some_string.encode(encoding) est plus Pythonique que d'utiliser le constructeur, parce que c'est le plus auto-documentant - "prendre cette chaîne et l'encoder avec cet encodage" est plus clair que bytes(some_string, encoding) - il n'y a pas de verbe explicite lorsque vous utilisez le constructeur.

Modifier: J'ai vérifié la source Python. Si vous passez une chaîne Unicode à bytes en utilisant CPython, il appelle PyUnicode_AsEncodedString, qui est la mise en œuvre de encode; donc vous passez juste un niveau d'indirection si vous appelez encode toi même.

Aussi, voir le commentaire de Serdalis - unicode_string.encode(encoding) est aussi plus pythonique car son inverse est byte_string.decode(encoding) et la symétrie est sympa.


357
2017-09-28 15:27



C'est plus facile que ce qu'on pense:

my_str = "hello world"
my_str_as_bytes = str.encode(my_str)
type(my_str_as_bytes) # ensure it is byte representation
my_decoded_str = my_str_as_bytes.decode()
type(my_decoded_str) # ensure it is string representation

151
2017-07-06 07:09



le absolument Le meilleur moyen n'est ni l'un ni l'autre, mais le troisième. Le premier paramètre à encode  par défaut  'utf-8' depuis Python 3.0. Ainsi, le meilleur moyen est

b = mystring.encode()

Ce sera également plus rapide, car l'argument par défaut ne résulte pas dans la chaîne "utf-8" dans le code C, mais NULL, lequel est beaucoup plus rapide à vérifier!

Voici quelques horaires:

In [1]: %timeit -r 10 'abc'.encode('utf-8')
The slowest run took 38.07 times longer than the fastest. 
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 183 ns per loop

In [2]: %timeit -r 10 'abc'.encode()
The slowest run took 27.34 times longer than the fastest. 
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 137 ns per loop

Malgré l’avertissement, les temps étaient très stables après des essais répétés - l’écart n’était que de 2% environ.


En utilisant encode() sans un argument n'est pas compatible Python 2, comme dans Python 2 le codage de caractères par défaut est ASCII.

>>> 'äöä'.encode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

37
2017-07-23 20:35



Vous pouvez simplement convertir la chaîne en octets en utilisant:

a_string.encode()

et vous pouvez simplement convertir des octets en chaîne en utilisant:

some_bytes.decode()

bytes.decode et str.encode avoir encoding='utf-8' comme valeur par défaut.

Les fonctions suivantes (extraites de Python efficace) peut être utile pour convertir str à bytes et bytes à str:

def to_bytes(bytes_or_str):
    if isinstance(bytes_or_str, str):
        value = bytes_or_str.encode() # uses 'utf-8' for encoding
    else:
        value = bytes_or_str
    return value # Instance of bytes


def to_str(bytes_or_str):
    if isinstance(bytes_or_str, bytes):
        value = bytes_or_str.decode() # uses 'utf-8' for encoding
    else:
        value = bytes_or_str
    return value # Instance of str

25
2017-09-04 12:42



so_string = 'stackoverflow'
so_bytes = so_string.encode( )

8
2018-04-05 16:16