Pourquoi ne pas utiliser sys.setdefaultencoding("utf-8") dans un script py?
4 réponses
selon la documentation: cela vous permet de passer de L'ASCII par défaut à D'autres encodages tels que UTF-8, que L'exécution Python utilisera chaque fois qu'il devra décoder un tampon de chaîne vers unicode.
cette fonction n'est disponible qu'au démarrage de Python, lorsque Python scanne l'environnement. Il doit être appelé dans un module à l'échelle du système, sitecustomize.py
, après que ce module a été évalué, la fonction setdefaultencoding()
est retirée du module sys
.
La seule façon de l'utiliser est avec un rechargement hack qui apporte de l'attribut.
aussi, l'utilisation de sys.setdefaultencoding()
a toujours été découragée , et il est devenu un no-op dans py3k. L'encodage de py3k est câblé à "utf-8" et sa modification soulève une erreur.
je suggère quelques conseils pour la lecture:
- http://blog.ianbicking.org/illusive-setdefaultencoding.html
- http://nedbatchelder.com/blog/200401/printing_unicode_from_python.html
- http://www.diveintopython3.net/strings.html#one-ring-to-rule-them-all
- http://boodebr.org/main/python/all-about-python-and-unicode
- http://blog.notdot.net/2010/07/Getting-unicode-right-in-Python
tl; dr
la réponse est jamais ! (sauf si vous savez vraiment ce que vous faites)
9/10 fois la solution peut être résolue avec une bonne compréhension de l'encodage/décodage.
1/10 les gens ont un endroit ou un environnement mal défini et ont besoin de définir:
PYTHONIOENCODING="UTF-8"
dans leur environnement pour résoudre les problèmes d'impression sur console.
Que fait-il?
(barred through to avoid re-use) change l'encodage/décodage par défaut utilisé chaque fois que Python 2.x doit convertir un Unicode () en str () (et vice-versa) et l'encodage n'est pas donné. I. e: sys.setdefaultencoding("utf-8")
str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC")
En Python 2.x, le codage par défaut est défini à ASCII et les exemples ci-dessus échoueront avec:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
(ma console est configuré comme UTF-8, donc "€" = '\xe2\x82\xac'
, donc exception sur \xe2
)
ou
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
permettra à ces derniers de travailler pour me , mais ne fonctionnera pas nécessairement pour les personnes qui n'utilisent pas UTF-8. la valeur par défaut de ASCII garantit que les hypothèses d'encodage ne sont pas transformées en code sys.setdefaultencoding("utf-8")
Console
a aussi pour effet secondaire d'apparaître pour fixer sys.setdefaultencoding("utf-8")
sys.stdout.encoding
, utilisé lors de l'impression des caractères à la console. Python utilise la locale de l'utilisateur (Linux/OS X/Un*x) ou le codepage (Windows) pour définir ceci. De temps en temps, la locale d'un utilisateur est cassée et il suffit de PYTHONIOENCODING
pour corriger le encodage de la console .
exemple:
$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()
$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€
Ce qui est si mal avec sys.setdefaultencoding ("utf-8") ?
les gens se sont développés contre Python 2.x de 16 ans sur la compréhension que l'encodage par défaut est ASCII. UnicodeError
les méthodes de gestion des exceptions ont été écrites pour gérer les conversions string to Unicode sur les chaînes qui contiennent des non-ASCII.
de https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code /
def welcome_message(byte_string):
try:
return u"%s runs your business" % byte_string
except UnicodeError:
return u"%s runs your business" % unicode(byte_string,
encoding=detect_encoding(byte_string))
print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))
avant de définir defaultencoding ce code ne pourrait pas décoder le " Å " dans l'encodage ascii et ensuite entrer le gestionnaire d'exception pour deviner l'encodage et le transformer correctement en unicode. Impression: Angstrom (Å®) gère votre entreprise. Une fois que vous avez défini le defaultencoding à utf-8, le code va trouver que le byte_string peut être interprété comme utf-8 et il va donc modifier les données et retourner ceci à la place: Angstrom (¿) exécute votre affaires.
changer ce qui devrait être une constante aura des effets dramatiques sur les modules dont vous dépendez. Il est préférable de simplement corriger les données entrant et sortant de votre code.
exemple de problème
alors que le paramétrage de defaultencoding à UTF-8 n'est pas la cause fondamentale dans l'exemple suivant, il montre comment les problèmes sont masqués et comment, lorsque l'encodage d'entrée change, le code se brise en une manière peu évidente: UnicodeDecodeError: 'utf8' codec ne peut pas décoder les octets 0x80 en position 3131: invalid octet de départ
#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u
chmod +x test.py
./test.py
moçambique
moçambique
./test.py > output.txt
Traceback (most recent call last):
File "./test.py", line 5, in <module>
print u
UnicodeEncodeError: 'ascii' codec can't encode character
u'\xe7' in position 2: ordinal not in range(128)
sur les travaux shell, l'envoi à sdtout Non , donc c'est un contournement, pour écrire à stdout .
j'ai fait une autre approche, qui n'est pas exécutée si sys.la sortie standard stdout.l'encodage n'est pas défini, ou en d'autres mots , il faut exporter PYTHONIOENCODING=UTF-8 en premier pour écrire à stdout.
import sys
if (sys.stdout.encoding is None):
print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
exit(1)
donc, en utilisant le même exemple:
export PYTHONIOENCODING=UTF-8
./test.py > output.txt
fonctionnera
-
le premier danger réside dans
reload(sys)
.Lorsque vous rechargez un module, vous obtenez en fait deux copies du module dans votre exécution. Le vieux module est un objet Python comme tout le reste, et reste vivant tant qu'il y a des références à lui. Ainsi, la moitié des objets sera pointant vers l'ancien module, et la moitié de la nouvelle. quand vous faites quelques changements, vous ne le verrez jamais venir quand un objet aléatoire ne voit pas le changement:
(This is IPython shell) In [1]: import sys In [2]: sys.stdout Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8> In [3]: reload(sys) <module 'sys' (built-in)> In [4]: sys.stdout Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0> In [11]: import IPython.terminal In [14]: IPython.terminal.interactiveshell.sys.stdout Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
-
Maintenant,
sys.setdefaultencoding()
bonTout ce qu'il affecte est la conversion implicite
str<->unicode
. Maintenant,utf-8
est le codage le plus sain sur la planète (rétro-compatible avec ASCII et tout), la conversion maintenant "fonctionne juste", qu'est-ce qui pourrait aller mal?enfin, n'importe quoi. Et c'est le danger.
- il peut y avoir un code qui s'appuie sur le
UnicodeError
lancé pour l'entrée non-ASCII, ou fait le transcodage avec un gestionnaire d'erreurs, qui produit maintenant un résultat inattendu. Et puisque tout le code est testé avec le réglage par défaut, vous êtes strictement sur" unsupported "territoire ici , et personne ne vous donne des garanties sur la façon dont leur code se comportera. - le transcodage peut produire des résultats inattendus ou inutilisables si tout le système n'utilise pas UTF-8 parce que Python 2 a en fait plusieurs" encodages par défaut de chaîne de caractères " . (Rappelez-vous, un programme doit travailler pour le client, sur l'équipement du client.)
- encore une fois, la pire chose est vous ne saurez jamais que parce que la conversion est implicite -- vous ne savez pas vraiment quand et là où ça se passe. (Python Zen, koan 2 ahoy!) Vous ne saurez jamais pourquoi (et si) votre code fonctionne sur un système et les pauses sur l'autre. (Ou encore mieux, travaille en IDE et casse en console.)
- il peut y avoir un code qui s'appuie sur le