J'ai vu quelques scripts py qui l'utilisent en haut du script. Dans quels cas faut-il l'utiliser?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
J'ai vu quelques scripts py qui l'utilisent en haut du script. Dans quels cas faut-il l'utiliser?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Réponses:
Selon la documentation: Cela vous permet de passer de l'ASCII par défaut à d'autres encodages tels que UTF-8, que le runtime Python utilisera chaque fois qu'il doit décoder un tampon de chaîne en unicode.
Cette fonction n'est disponible qu'au démarrage de Python, lorsque Python analyse l'environnement. Il doit être appelé dans un module à l'échelle du système,, Une sitecustomize.py
fois ce module évalué, la setdefaultencoding()
fonction est supprimée du sys
module.
La seule façon de l'utiliser est avec un hack de rechargement qui ramène l'attribut.
De plus, l'utilisation de sys.setdefaultencoding()
a toujours été découragée , et elle est devenue un no-op dans py3k. L'encodage de py3k est câblé à "utf-8" et sa modification génère une erreur.
Je suggère quelques conseils pour lire:
sys.stdout
lorsqu'il a un None
encodage, comme lors de la redirection de la sortie d'un programme Python).
sys.setdefaultencoding()
a toujours été découragée"
UTF-8
. LC_ALL=en_US.UTF-8 python3 -c 'import sys; print(sys.stdout.encoding)'
donne UTF-8
mais LC_ALL=C python3 -c 'import sys; print(sys.stdout.encoding)'
donneANSI_X3.4-1968
(ou peut-être autre chose)
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 des personnes ont une langue ou un environnement mal défini et doivent définir:
PYTHONIOENCODING="UTF-8"
dans leur environnement pour résoudre les problèmes d'impression de la console.
(barré pour éviter la réutilisation) modifie l'encodage / décodage par défaut utilisé chaque fois que Python 2.x a besoin de convertir un Unicode () en str () (et vice-versa) et l'encodage n'est pas donné. C'est à dire:sys.setdefaultencoding("utf-8")
str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC")
Dans Python 2.x, l'encodage par défaut est défini sur 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ée en UTF-8, donc "€" = '\xe2\x82\xac'
, exception sur \xe2
)
ou
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
permettra à ceux-ci de travailler pour moi , 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 de codage ne sont pas intégrées dans le codesys.setdefaultencoding("utf-8")
a également pour effet secondaire de sembler corriger sys.setdefaultencoding("utf-8")
sys.stdout.encoding
, utilisé lors de l'impression de caractères sur la console. Python utilise les paramètres régionaux de l'utilisateur (Linux / OS X / Un * x) ou la page de codes (Windows) pour définir cela. Parfois, les paramètres régionaux d'un utilisateur sont défectueux et nécessitent simplementPYTHONIOENCODING
de corriger le codage 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"
€
Les gens développent contre Python 2.x depuis 16 ans, sachant que l'encodage par défaut est ASCII. UnicodeError
Des méthodes de gestion des exceptions ont été écrites pour gérer les conversions chaîne en Unicode sur les chaînes qui contiennent des caractères 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 le codage par défaut, ce code ne pouvait pas décoder le «Å» dans le codage ascii et entrerait ensuite dans le gestionnaire d'exceptions pour deviner le codage et le transformer correctement en unicode. Impression: Angstrom (Å®) dirige votre entreprise. Une fois que vous avez défini le codage par défaut sur utf-8, le code trouvera que byte_string peut être interprété comme utf-8 et ainsi il modifiera les données et retournera ceci à la place: Angstrom (Ů) dirige votre entreprise.
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.
Bien que le paramètre de codage par défaut en UTF-8 ne soit pas la cause principale dans l'exemple suivant, il montre comment les problèmes sont masqués et comment, lorsque le codage d'entrée change, le code se brise de manière non évidente: UnicodeDecodeError: le codec 'utf8' peut 't décoder l'octet 0x80 en position 3131: octet de départ invalide
sys.setdefaultencoding("utf-8")
, il est bon de faire en sorte que le code se comporte davantage comme Python 3. Nous sommes en 2017 maintenant. Même lorsque vous avez écrit la réponse en 2015, je pense qu'il valait déjà mieux regarder en avant plutôt qu'en arrière. C'était en fait la solution la plus simple pour moi, quand j'ai trouvé que mon code se comportait différemment dans Python 2 selon que la sortie était redirigée (très mauvais problème pour Python 2). Inutile de dire que je l'ai déjà fait # coding: utf-8
et que je n'ai pas besoin de solutions de contournement pour Python 3 (je dois en fait masquer la setdefaultencoding
vérification de la version).
sys.setdefaultencoding("utf-8")
ne rend pas votre code Py 2.x compatible avec Python 3. Il ne corrige pas non plus les modules externes qui supposent que l'encodage par défaut est ASCII. Rendre votre code compatible Python 3 est très simple et ne nécessite pas ce méchant hack. Par exemple, pourquoi cela pose des problèmes très réels, voir mon expérience avec Amazon qui joue avec cette hypothèse: stackoverflow.com/questions/39465220/…
PYTHONIOENCODING="UTF-8"
j'ai aidé mon environnement Python2.7 Django-1.11. Merci.
detect_encoding
.
detect_encoding
soit une méthode qui pourrait détecter le codage d'une chaîne en fonction d'indices de langage.
#!/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 le shell fonctionne, l'envoi à sdtout non, donc c'est une solution de contournement, pour écrire sur stdout.
J'ai fait une autre approche, qui n'est pas exécutée si sys.stdout.encoding n'est pas défini, ou en d'autres termes, il faut d'abord exporter PYTHONIOENCODING = UTF-8 pour écrire dans 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
marchera
Le premier danger réside dans reload(sys)
.
Lorsque vous rechargez un module, vous obtenez en fait deux copies du module dans votre runtime. L'ancien module est un objet Python comme tout le reste, et reste en vie tant qu'il y a des références. Ainsi, la moitié des objets pointeront vers l'ancien module et l'autre moitié vers le nouveau. Lorsque vous apportez un changement, vous ne le verrez jamais venir lorsqu'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()
bon
Tout ce que cela affecte, c'est la conversion implicitestr<->unicode
. Maintenant, utf-8
est le codage le plus sain sur la planète (rétrocompatible avec ASCII et tout), la conversion maintenant "fonctionne juste", qu'est - ce qui pourrait éventuellement mal tourner?
Eh bien, n'importe quoi. Et c'est le danger.
UnicodeError
lancement pour une entrée non ASCII, ou qui effectue le transcodage avec un gestionnaire d'erreurs, ce qui produit maintenant un résultat inattendu. Et comme tout le code est testé avec le paramètre par défaut, vous êtes strictement sur le territoire "non pris en charge" ici , et personne ne vous donne de garanties sur le comportement de leur code.