Beste manier om string naar bytes te converteren in Python 3?

Er lijken twee verschillende manieren te zijn om een ​​string naar bytes te converteren, zoals te zien is in de antwoorden op TypeError: ‘str’ ondersteunt de bufferinterface niet

Welke van deze methoden zou beter of Pythonischer zijn? Of is het gewoon een kwestie van persoonlijke voorkeur?

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

Antwoord 1, autoriteit 100%

Als je de documenten voor bytes bekijkt, wordt je verwezen naar bytearray:

bytearray([bron[ encoding[ errors]]])

Retourneer een nieuwe array van bytes. Het bytearray-type is een veranderlijke reeks gehele getallen in het bereik 0 <= x < 256. Het heeft de meeste van de gebruikelijke methoden voor veranderlijke sequenties, beschreven in Mutable Sequence Types, evenals de meeste methoden die het bytes-type heeft, zie Bytes en Byte Array Methods.

De optionele bronparameter kan worden gebruikt om de array op een paar verschillende manieren te initialiseren:

Als het een string is, moet u ook de parameters voor codering (en optioneel fouten) opgeven; bytearray() converteert de string vervolgens naar bytes met str.encode().

Als het een geheel getal is, heeft de array die grootte en wordt deze geïnitialiseerd met null-bytes.

Als het een object is dat voldoet aan de bufferinterface, wordt een alleen-lezen buffer van het object gebruikt om de bytes-array te initialiseren.

Als het een iterabel is, moet het een itereerbaar zijn van gehele getallen in het bereik 0 <= x < 256, die worden gebruikt als de initiële inhoud van de array.

Zonder een argument wordt een array van grootte 0 gemaakt.

Dus bytes kunnen veel meer doen dan alleen een string coderen. Het is Pythonic dat je de constructor kunt aanroepen met elk type bronparameter dat logisch is.

Voor het coderen van een string, denk ik dat some_string.encode(encoding) meer Pythonisch is dan het gebruik van de constructor, omdat het de meest zelfdocumenterende is — "neem deze string en codeer hem met deze codering" is duidelijker dan bytes(some_string, encoding) — er is geen expliciet werkwoord wanneer je de constructor gebruikt.

Bewerken: ik heb de Python-bron gecontroleerd. Als u een unicode-tekenreeks doorgeeft aan bytes met behulp van CPython, roept het PyUnicode_AsEncodedString, wat de implementatie is van encode; dus je slaat gewoon een niveau van indirectheid over als je zelf encode aanroept.

Zie ook de opmerking van Serdalis — unicode_string.encode(encoding) is ook meer Pythonisch omdat het inverse byte_string.decode(encoding) is en symmetrie mooi is.


Antwoord 2, autoriteit 71%

Het is makkelijker dan gedacht:

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

Antwoord 3, autoriteit 28%

De absoluut beste manier is geen van de twee, maar de derde. De eerste parameter om encode standaard ingesteld op 'utf-8' sinds Python 3.0. Dus de beste manier is

b = mystring.encode()

Dit gaat ook sneller, omdat het standaardargument niet resulteert in de tekenreeks "utf-8" in de C-code, maar in NULL, wat veel sneller te controleren is!

Hier zijn enkele tijden:

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

Ondanks de waarschuwing waren de tijden zeer stabiel na herhaalde runs – de afwijking was slechts ~2 procent.


Het gebruik van encode() zonder een argument is niet compatibel met Python 2, aangezien in Python 2 de standaardtekencodering ASCII is.

>>> 'aoa'.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)

Antwoord 4, autoriteit 3%

Antwoord voor een iets ander probleem:

Je hebt een reeks onbewerkte unicode die is opgeslagen in een str-variabele:

s_str: str = "\x00\x01\x00\xc0\x01\x00\x00\x00\x04"

Je moet de letterlijke byte van die unicode kunnen krijgen (voor struct.unpack(), enz.)

s_bytes: bytes = b'\x00\x01\x00\xc0\x01\x00\x00\x00\x04'

Oplossing:

s_new: bytes = bytes(s, encoding="raw_unicode_escape")

Referentie (scroll omhoog voor standaardcoderingen):

Python-specifieke coderingen

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes