Poursuivant l'article Hier, cette fois, je vais résumer ma propre politique concernant les chaînes de caractères en Python3.
Ce n'est ni bon ni mauvais, c'est juste qu'il n'y a pas beaucoup de cas où votre code doit actuellement traiter des octets.
La chaîne d'octets est codée par une méthode de codage spécifique, et est exprimée par «b'a» dans le littéral. D'autre part, une chaîne de caractères est un tableau de points de code Unicode, et est exprimée par `` a '' en littéraux.
Je l'ai écrit brièvement, mais à ce stade, vous pouvez voir la différence de manipulation avec Python 2.
python
(py3.4)~ » ipython
(réduction)
>>> b'a' #Chaîne d'octets
Out[1]: b'a'
#La notation littérale ne peut pas être utilisée lorsqu'elle contient des caractères non ASCII
#La chaîne doit être encodée avec une méthode d'encodage spécifique
>>> b'Ah'
File "<ipython-input-2-c12eb8e58bcd>", line 1
b'Ah'
^
SyntaxError: bytes can only contain ASCII literal characters.
>>> 'Ah'.encode('utf-8') #Chaîne->Chaîne d'octets(Encoder)
Out[3]: b'\xe3\x81\x82'
>>> 'Ah' #Chaîne
Out[4]: 'Ah'
>>> b'\xe3\x81\x82'.decode('utf-8') #Chaîne d'octets->Chaîne(Décoder)
Out[5]: 'Ah'
# Python2(Republier)
(py2.7)~ » ipython
(réduction)
>>> 'Ah' #Chaîne d'octets
Out[1]: '\xe3\x81\x82'
>>> u'Ah' #Chaîne Unicode
Out[2]: u'\u3042'
>>> 'Ah'.decode('utf-8') (or unicode('Ah', 'utf-8')) #Chaîne d'octets->Chaîne Unicode(=Décoder)
Out[3]: u'\u3042'
>>> u'Ah'.encode('utf-8') #Chaîne Unicode->Chaîne d'octets(=Encoder)
Out[4]: '\xe3\x81\x82'
Si vous vérifiez avec la fonction type
, vous pouvez voir que la chaîne d'octets est de type octets
/ la chaîne de caractères est de type str
.
python
>>> type(b'a')
Out[6]: bytes #≒ Type de chaîne Python2
>>> type('a')
Out[7]: str #≒ Type unicode Python2
De plus, comme mentionné ci-dessus, les chaînes d'octets Python3 ne sont pas des "chaînes de caractères". Par conséquent, il ne peut pas être concaténé avec une chaîne de caractères et les méthodes prises en charge sont différentes. Ce point est relativement important, car il s'agit de la même chaîne de caractères que dans Python2, le traitement progresse en quelque sorte et finalement "UnicodeEncodeError is ga", mais en Python3 cela devient "erreur due à un type différent" et sortie d'erreur / Le lieu de l'événement est relativement facile à comprendre.
python
>>> s = 'str' #Chaîne
>>> b = b'byte' #Chaîne d'octets
>>> s + b #Chaîne+La chaîne d'octets est une erreur
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-20-5fe2240a1b50> in <module>()
----> 1 s + b
TypeError: Can't convert 'bytes' object to str implicitly
>>> s.find('t') #La chaîne prend en charge la méthode find
Out[11]: 1
>>> b.find('y') #La chaîne d'octets ne prend pas en charge la méthode find.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-24-e1b070a5aaba> in <module>()
----> 1 b.find('y')
TypeError: Type str doesn't support the buffer API
De plus, à partir de Python 3.2, il semble sélectionner la méthode de codage appropriée à partir de la valeur de locale même lorsque la sortie standard est connectée à un autre que le terminal. Par conséquent, dans Python2, les cas suivants avec UnicodeEncodeError fonctionnent également normalement.
(réf.) http://methane.hatenablog.jp/entry/20120806/1344269400 Addendum
python
(py3.4)~ » cat test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
print('Ah' + 'Dire')
#Exécuter dans le terminal(L'entrée / sortie standard est connectée à la borne)
(py3.4)~ » python test.py
Ah
#Rediriger vers le fichier(L'entrée / sortie standard est connectée à une autre que la borne)
(py3.4)~ » python test.py > test.txt
(py3.4)~ » cat test.txt
Ah
Même si vous ne signalez pas de manière flagrante votre mort, vous pouvez toujours rencontrer une erreur UnicodeEncodeError. Par exemple, lors de l'exécution à partir de cron, vous ne pouvez pas sélectionner la méthode de codage à partir des paramètres régionaux et essayer d'encoder / décoder avec ASCII, et vous vous retrouvez généralement avec UnicodeEncodeError.
(ref.) http://www.python.jp/pipermail/python-ml-jp/2014-November/011311.html (La publication est extrêmement opportune)
Compte tenu de cela, il peut être préférable de toujours spécifier la méthode de codage avec la variable d'environnement PYTHONIOENCODING
sans compter sur les paramètres régionaux.
(ref.) http://methane.hatenablog.jp/entry/20120806/1344269400 (ref.) http://www.python.jp/pipermail/python-ml-jp/2014-November/011314.html
Vous pouvez utiliser sys.stdin.buffer
(entrée standard) / sys.stdout.buffer
(sortie standard) pour gérer des chaînes d'octets au lieu de chaînes.
python
(py3.4)~ » cat test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
#print('Ah' + 'Dire') #l'impression est sys.Écrire dans stdout
sys.stdout.write('Ah' + 'Dire' + '\n') # sys.Ecrire une chaîne dans stdout
sys.stdout.buffer.write(('Ah' + 'Dire' + '\n').encode('utf-8')) # sys.stdout.Ecrire une chaîne d'octets dans la mémoire tampon
#Exécuter dans le terminal
(py3.4)~ » python test.py
Ah
Ah
#Rediriger vers le fichier
(py3.4)~ » python test.py > test.txt
(py3.4)~ » cat test.txt
Ah
Ah
Encore une fois, dans Python 3, les octets et les chaînes sont complètement différents. Par conséquent, la chaîne d'octets ne peut pas être écrite dans sys.stdout
qui écrit la chaîne de caractères, et la chaîne de caractères ne peut pas être écrite dans sys.stdout.buffer
qui écrit la chaîne d'octets.
python
>>> import sys
#Flux de texte(ref. https://docs.python.org/3/library/io.html#io.TextIOWrapper)
>>> type(sys.stdout)
Out[2]: _io.TextIOWrapper
#Flux d'octets(ref. https://docs.python.org/3/library/io.html#io.BufferedWriter)
>>> type(sys.stdout.buffer)
Out[3]: _io.BufferedWriter
#Impossible d'écrire des octets dans le flux de texte
>>> sys.stdout.write('a'.encode('utf-8'))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-581ae8b6af82> in <module>()
----> 1 sys.stdout.write('a'.encode('utf-8'))
TypeError: must be str, not bytes
#Les chaînes ne peuvent pas être écrites dans bytestream
>>> sys.stdout.buffer.write('a')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-42da1d141b96> in <module>()
----> 1 sys.stdout.buffer.write('a')
TypeError: 'str' does not support the buffer interface
Recommended Posts