Qu'est-ce qu'un bytesting Python?
Tout ce que je peux trouver, ce sont des rubriques sur la manière de coder en bytestring ou de décoder en ascii
ou utf-8
. J'essaie de comprendre comment cela fonctionne sous le capot. Dans une chaîne ASCII normale, il s'agit d'un tableau ou d'une liste de caractères, et chaque caractère représente une valeur ASCII comprise entre 0 et 255, c'est ainsi que vous savez quel caractère est représenté par le nombre. En Unicode, c'est la représentation de 8 ou 16 octets du caractère qui vous indique de quel caractère il s'agit.
Alors, quel est un bytestring? Comment Python sait-il quels caractères représenter comme quoi? Comment ça marche sous le capot? Puisque vous pouvez imprimer ou même renvoyer ces chaînes et que la représentation sous forme de chaîne est affichée, je ne comprends pas très bien ...
Ok, donc mon point est définitivement être manqué ici. On m'a dit que c'était une séquence d'octets immuable sans aucune interprétation particulière de interprétation.
Une séquence d'octets .. Bon, disons un octet:'a'.encode()
renvoie b'a'
.
Assez simple. Pourquoi puis-je lire le a ?
Disons que je reçois la valeur ASCII pour a , en procédant comme suit:printf "%d" "'a"
Il retourne 97 . OK, bien, la valeur entière pour le caractère ASCII a . Si nous interprétons 97 comme ASCII, disons dans C char
, alors nous aurons la lettre a
. C'est suffisant. Si nous convertissons la représentation en octets en bits, nous obtenons ceci:
01100001
2 ^ 0 + 2 ^ 5 + 2 ^ 6 = 97. Cool.
Alors pourquoi 'a'.encode()
renvoie-t-il b'a'
au lieu de 01100001
??
Si c'est sans un interprétation particulier, ne devrait-il pas retourner quelque chose comme b'01100001'
?
Il semble comme si cela l’interprétait comme ASCII.
Quelqu'un a mentionné qu'il appelle __repr__
sur la chaîne d'octets, de sorte qu'il s'affiche sous une forme lisible par l'homme. Cependant, même si je fais quelque chose comme:
with open('testbytestring.txt', 'wb') as f:
f.write(b'helloworld')
Still insérera helloworld
sous forme de chaîne normale dans le fichier, et non sous forme de séquence d'octets ... Un bytest est-il donc en ASCII?
Python ne sait pas savoir comment représenter un bytestring. C'est le but.
Lorsque vous affichez un caractère de valeur 97 dans pratiquement n'importe quelle fenêtre de sortie, vous obtenez le caractère "a", mais cela ne fait pas partie de l'implémentation; c'est juste une chose qui se trouve être vraie localement. Si vous voulez un encodage, vous n'utilisez pas de bytestring. Si vous utilisez bytestring, vous n'avez pas d'encodage.
Votre article sur les fichiers .txt montre que vous avez mal compris ce qui se passe. Vous voyez, les fichiers de texte brut n'ont pas non plus d'encodage. Ils ne sont qu'une série d'octets. Ces octets sont traduits en lettres par l'éditeur de texte mais il n'y a aucune garantie du tout que quelqu'un ouvrant votre fichier verra la même chose que vous si vous sortez du jeu commun de caractères ASCII.
On pense souvent à tort que le texte est ascii ou utf8 ou cp1252 et que les octets sont donc du texte.
Le texte n'est que du texte, au sens où les images ne sont que des images. Le fait de stocker du texte ou des images sur un disque consiste à coder ces données dans une séquence d'octets. Il existe de nombreuses manières de coder des images en octets: Jpeg, png, svg, et de nombreuses manières de coder du texte, ascii, utf8 ou cp1252.
Une fois le codage effectué, les octets ne sont que des octets. Les octets ne sont plus des images, ils ont oublié les couleurs qu’ils désignent; bien qu'un décodeur de format d'image puisse récupérer cette information. Les octets ont pareillement oublié les lettres qu’ils étaient. En fait, les octets ne se souviennent pas s’il s’agissait d’images ou de texte. Seules les connaissances hors bande (nom de fichier, en-têtes de média, etc.) peuvent deviner ce que ces octets doivent signifier, et même cela peut être erroné (en cas de corruption des données)
ainsi, en python (py3), nous avons deux types de choses qui pourraient autrement se ressembler; Pour le texte, nous avons str
, qui sait que c'est du texte; il sait quelles lettres il est supposé vouloir dire. Il ne sait pas quels octets pourraient être, car les lettres ne sont pas des octets. Nous avons aussi bytestring
, qui ne sait pas s'il s'agit de texte, d'images ou de tout autre type de données.
Les deux types sont superficiellement similaires, car ils sont tous deux des séquences de choses, mais les choses dont ils sont des séquences sont très différents.
Au niveau de la mise en œuvre, str
est stocké en mémoire sous la forme UCS-?
où le? Si sa mise en œuvre est définie, il peut s’agir de UCS4, UCS2 ou UCS1, en fonction des options de temps de compilation et des points de code présents dans la chaîne représentée.
éditer "mais pourquoi"?
Certaines choses qui ressemblent à du texte sont en réalité définies dans d'autres termes. Les nombreux protocoles Internet du monde en sont un très bon exemple. Par exemple, HTTP est un protocole "texte" qui est en fait défini en utilisant la syntaxe ABNF courante dans les RFC. Ces protocoles sont exprimés en octets, pas en caractères, bien qu'un codage informel puisse également être suggéré:
Les règles se résolvent en une chaîne de valeurs terminales, parfois appelée
personnages. En ABNF, un caractère est simplement un entier non négatif.
Dans certains contextes, un mappage (codage) spécifique de valeurs dans une
jeu de caractères (tel que ASCII) sera spécifié.
Cette distinction est importante car il n’est pas possible d’envoyer du texte sur Internet, vous ne pouvez envoyer que des octets. Dire "texte mais en codage" foo "" rend le format beaucoup plus complexe, car les clients et les serveurs doivent maintenant comprendre en quelque sorte le domaine du codage, de la même manière, espérons-le, car ils doivent finalement transmettre les données sous forme d'octets en tous cas. Cela est doublement inutile car ces protocoles concernent de toute façon rarement la gestion de texte et ne sont que pratiques pour les développeurs. Ni les propriétaires de serveur ni les utilisateurs finaux ne sont jamais intéressés par la lecture des mots Transfer-Encoding: chunked
, tant que le serveur et le navigateur le comprennent correctement.
En comparaison, lorsque vous travaillez avec du texte, vous ne vous souciez pas vraiment de la manière dont il est codé. Vous pouvez exprimer le "Heävy Mëtal Ümlaüts" comme vous le souhaitez, sauf "Heδvy Mλtal άmlaόts"
les types distincts vous permettent donc de dire "cette valeur" signifie "texte" ou "octets".
Comme son nom l'indique, un Python3 bytestring
(ou simplement un str
in Python 2.7) est une chaîne de bytes. Et, comme d'autres l'ont souligné, c'est immuable.
Il est distinct d'un Python3 str
(ou, de façon plus descriptive, d'un unicode
en Python 2.7) qui est une chaîne De abstract caractères Unicode (aka UTF-32 , bien que Python3 ajoute une compression sophistiquée sous le capot pour réduire l’empreinte mémoire réelle, comme sur UTF-8, peut-être même de manière plus générale).
Il y a essentiellement trois façons de "interpréter" ces octets. Vous pouvez regarder la valeur numérique d'un élément, comme ceci:
>>> ord(b'Hello'[0]) # Python 2.7 str
72
>>> b'Hello'[0] # Python 3 bytestring
72
Vous pouvez également demander à Python d’émettre un ou plusieurs éléments sur le terminal (ou un fichier, un périphérique, une socket, etc.) en caractères 8 bits, comme ceci:
>>> print b'Hello'[0] # Python 2.7 str
H
>>> import sys # Python 3 bytestring
>>> sys.stdout.write(str(b'Hello'[0:1], sys.stdout.encoding))
H
Comme Jack l'a laissé entendre, dans ce dernier cas, il s'agit de votre terminal interprétant Le caractère, pas de Python (bien que, dans le cas de Python3, vous do ayez à convertir en str
être compatible avec les futurs terminaux qui pourraient ne pas être basés sur des octets. Ceci est à l’origine de la confusion qui règne à l’OMI).
Enfin, comme vous avez pu le constater dans vos propres recherches, vous pouvez également obtenir que Python interprète une bytestring
. Par exemple, vous pouvez construire un objet abstrait unicode
comme ceci dans Python 2.7:
>>> u1234 = unicode(b'\xe1\x88\xb4', 'utf-8')
>>> u1234
u'\u1234'
>>> type(u1234)
<type 'unicode'>
>>> len(u1234)
1
>>>
Ou comme ceci dans Python 3:
>>> u1234 = str(b'\xe1\x88\xb4', 'utf-8')
>>> '\\u%04x' % ord(u1234)
\u1234
>>> type(u1234)
<class 'str'>
>>> len(u1234)
1
Mais l'abstraction unicode ne se produit pas automatiquement si vous ne le souhaitez pas. L'intérêt d'un bytestring
est que vous pouvez accéder directement aux octets. Même dans l'exemple ci-dessus de Python2.7:
>>> len(b'\xe1\x88\xb4')
3
>>> b'\xe1\x88\xb4'[0]
'\xe1'
Vous pouvez aussi faire d’autres choses merveilleuses avec bytestring
s, par exemple savoir s’ils vont tenir dans un espace réservé d’un fichier, les envoyer directement par une socket, calculer correctement le champ HTTP content-length
et éviter Python Bug 8260 . En bref, utilisez bytestring
s lorsque vos données sont traitées et stockées en octets.
Les objets octets sont des séquences immuables d'un octet. Les docs expliquent très bien ce qu’ils sont et comment les utiliser.