Points à garder à l'esprit lors du traitement des chaînes en Python2

UnicodeEncodeError, le plus grand ennemi naturel (exagération) des programmeurs Python (avec Python2) qui gèrent le japonais. La personne à côté de moi hier était la proie, et pendant que j'aidais à le résoudre, j'ai pu régler un peu le sens du traitement des chaînes dans Python 2. (Je veux bientôt mettre sur pied une version de Python 3)

Conclusion personnelle

Chaîne d'octets et chaîne Unicode

La chaîne d'octets est codée par une méthode de codage spécifique (ex. Utf-8), et est exprimée par `` ça '' dans le littéral. D'un autre côté, une chaîne de caractères Unicode est un arrangement de points de code Unicode, et dans le littéral, ʻu est ajouté comme ʻu'that'.

python


(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 str / la chaîne unicode est de type ʻunicode`.

python


>>> type('a')
Out[5]: str

>>> type(u'a')
Out[6]: unicode

De plus, dans Python2, les chaînes d'octets et les chaînes Unicode sont des chaînes et peuvent être concaténées.

python


>>> u'a' + 'a'
Out[7]: u'aa'

quoi. Il n'y a pas de problème.

Oui, je dois gérer le japonais (pour être exact, tous les caractères non ASCII)! Comme vous pouvez le voir dans la sortie de l'exemple ci-dessus, la combinaison d'une chaîne Unicode et d'une chaîne d'octets produit une chaîne Unicode. Dans le processus, vous devez décoder la chaîne d'octets en une chaîne Unicode, mais le problème ici est que la chaîne Python n'a aucune information sur son propre codage.

«Si vous ne savez pas comment encoder, vous pouvez le décoder en ASCII», dit Python, et Hello UnicodeEncodeError. Il est rare que les littéraux fassent de telles erreurs, mais il est facile de faire des erreurs si vous ne faites pas attention aux chaînes de caractères reçues de l'extérieur de votre propre programme (y compris les entrées / sorties standard).

python


>>> u'a' + 'Ah' #Chaîne Unicode et chaîne d'octets(Non-ASCII)Combiner
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-8-084e015bd795> in <module>()
----> 1 u'a' + 'Ah'

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)

>>> u'a' + 'Ah'.decode('utf-8') #Chaîne d'octets->Chaîne Unicode
Out[9]: u'a\u3042'

>>> print(u'a' + 'Ah'.decode('utf-8'))
a ah

La raison du passage à une chaîne Unicode au lieu d'une chaîne d'octets est qu'il est souvent plus pratique de travailler avec une chaîne au niveau du point de code qu'au niveau des octets. Par exemple, si vous voulez compter le nombre de caractères, vous pouvez utiliser la fonction len pour les chaînes Unicode. D'autre part, une chaîne d'octets renvoie le nombre d'octets, elle ne peut donc pas être utilisée avec cette intention.

python


>>> len(u'Ah')
Out[11]: 3

>>> len('Ah')
Out[12]: 9

La chaîne de caractères Unicode est la meilleure! Je ne voulais pas de chaîne de caractères d'octets!

N'est pas. À titre d'exemple, considérons le programme simple suivant.

test.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

print(u'Ah' + u'Dire')

Essayez de l'exécuter dans le terminal. La majorité des gens peuvent probablement le faire sans problème.

python


(py2.7)~ » python test.py
Ah

Alors qu'en est-il de la redirection des résultats de l'exécution vers un fichier? Il existe de nombreux environnements dans lesquels UnicodeEncodeError se produit, comme illustré ci-dessous.

python


(py2.7)~ » python test.py > test.txt
Traceback (most recent call last):
  File "test.py", line 4, in <module>
    print(u'Ah')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

Méthode de localisation et d'encodage

Dans l'exemple print (u'Ai '), une chaîne de caractères Unicode est passée à la sortie standard, mais à ce stade, la chaîne de caractères Unicode-> octet est convertie (encodée). Si l'entrée / sortie standard est connectée au terminal, Python sélectionnera automatiquement la méthode de codage appropriée à partir de la valeur de locale (ex. Variable d'environnement LANG). D'autre part, lorsque l'entrée / sortie standard est connectée à un autre que le terminal par redirection, etc., les informations pour sélectionner une méthode de codage appropriée ne peuvent pas être obtenues, et le codage est tenté en ASCII, et dans la plupart des cas (= lorsque des caractères non-ASCII sont inclus). Échouer.

(ref.) http://blog.livedoor.jp/dankogai/archives/51816624.html

Le codage de la chaîne Unicode avant de la transmettre à la sortie standard peut résoudre ce problème.

test.py(Chaîne Unicode->Chaîne d'octets)


#!/usr/bin/env python
# -*- coding: utf-8 -*-

print((u'Ah' + u'Dire').encode('utf-8'))

J'ai toujours pensé

En spécifiant la variable d'environnement PYTHONIOENCODING, la méthode de codage utilisée peut être fixée indépendamment de la locale. Si vous spécifiez cela, vous n'avez pas à l'encoder un par un.

python


(py2.7)~ » cat test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

print(u'Ah' + u'Dire')
(py2.7)~ » PYTHONIOENCODING=utf-8 python test.py > test.txt
(py2.7)~ » cat test.txt
Ah

(ref.) http://methane.hatenablog.jp/entry/20120806/1344269400

Recommended Posts

Points à garder à l'esprit lors du traitement des chaînes en Python2
Points à garder à l'esprit lors du traitement des chaînes en Python 3
Points à garder à l'esprit lors du développement d'un robot d'exploration en Python
Points à garder à l'esprit lors de la copie de listes Python
Précautions lors de l'utilisation de Python avec AtCoder
Choses à garder à l'esprit lors de l'utilisation de cgi avec python.
Points à garder à l'esprit lors de l'utilisation de Python pour ceux qui utilisent MATLAB
Points à garder à l'esprit lors de la création d'outils automatisés pour l'atelier en Python
Points à garder à l'esprit lors du déploiement de Keras sur votre Mac
Points à garder à l'esprit lors de la conversion d'un vecteur de ligne en vecteur de colonne avec ndarray
Choses à noter lors de l'initialisation d'une liste en Python
Points à garder à l'esprit lors de la prédiction par lots avec GCP ML Engine
Choses à surveiller lors de l'utilisation d'arguments par défaut en Python
Résumé des points à garder à l'esprit lors de l'écriture d'un programme qui s'exécute sur Python 2.5
3 façons d'analyser les chaînes de temps avec python [Note]
Une manière intelligente de chronométrer le traitement avec Python
Erreur lors de la tentative d'installation de psycopg2 en Python
Traitement de fichiers en Python
Traitement multithread en python
Traitement de texte avec Python
Traitement des requêtes en Python
Comparer des chaînes en Python
Inverser les chaînes en Python
Comment prendre plusieurs arguments lors d'un traitement parallèle à l'aide du multitraitement en python
Comment mesurer le temps de traitement avec Python ou Java
Vue basée sur les classes Django
Points à garder à l'esprit lors du traitement des chaînes en Python2
Points à garder à l'esprit lors du traitement des chaînes en Python 3
Tenez compte du prétraitement courant lors du traitement du flux DynamoDB avec Lambda (Python)
Ce à quoi j'étais accro lorsque l'utilisateur de traitement est passé à Python
Comment quitter lors de l'utilisation de Python dans Terminal (Mac)
Je veux faire quelque chose avec Python à la fin
Je veux manipuler des chaînes dans Kotlin comme Python!
Traitement de texte UTF8 avec python
Pour vider stdout en Python
Connectez-vous au site Web en Python
Attention lorsque os.mkdir en Python
Collection de traitement d'image en Python
Comment développer en Python
Utilisation du mode Python dans le traitement
Publier sur Slack en Python
traitement python3 qui semble utilisable dans paiza
Ce à quoi j'étais accro lorsque l'utilisateur de traitement est passé à Python
Méthode d'écriture pratique lors de l'ajout continu à la liste en Python
Que faire lorsque "SSL: CERTIFICATE_VERIFY_FAILED _ssl.c: 1056" apparaît en Python
Autoriser Python à sélectionner la chaîne de caractères du fichier d'entrée dans le dossier
Ordre de traitement lors du chaînage dans PySpark
[Sous-processus] Lorsque vous souhaitez exécuter un autre programme Python en code Python
Laissez le traitement gênant à Python
Comment ne pas échapper au japonais en traitant avec JSON en Python
[Python] Comment faire PCA avec Python
traitement pour utiliser les données notMNIST en Python (et essayé de les classer)
Traitement du signal en Python (1): transformée de Fourier
Précautions lors de l'utilisation de Pit avec Python
Points à prendre en compte lors de l'attribution d'un nom au routage dynamique dans nuxt.js
Convertir Markdown en PDF en Python
Comment collecter des images en Python
100 Language Processing Knock Chapitre 1 en Python
Comportement lors de la liste dans Python heapq
[Introduction à Python3 Jour 13] Chapitre 7 Chaînes de caractères (7.1-7.1.1.1)
Comment utiliser SQLite en Python
Précautions lors de l'exécution de Python sur EC2 à partir d'AWS Lambda (Exécuter la commande)
Dans la commande python, python pointe vers python3.8