J'ai de nombreux problèmes "impossible d'encoder" et "impossible de décoder" avec Python lorsque j'exécute mes applications depuis la console. Mais dans l' IDE Eclipse PyDev , l'encodage de caractères par défaut est défini sur UTF-8 , et ça va.
J'ai cherché partout pour définir l'encodage par défaut, et les gens disent que Python supprime la sys.setdefaultencoding
fonction au démarrage et que nous ne pouvons pas l'utiliser.
Alors, quelle est la meilleure solution pour cela?
The best solution is to learn to use encode and decode correctly instead of using hacks.
Cela était certainement possible avec python2 au prix de toujours se souvenir de le faire / en utilisant systématiquement votre propre interface. Mon expérience suggère que cela devient très problématique lorsque vous écrivez du code que vous souhaitez utiliser à la fois avec python2 et python3.Réponses:
Voici une méthode plus simple (hack) qui vous rend la
setdefaultencoding()
fonction qui a été supprimée desys
:(Remarque pour Python 3.4+: se
reload()
trouve dans laimportlib
bibliothèque.)Cependant, ce n'est pas une chose sûre à faire : il s'agit évidemment d'un hack, car il
sys.setdefaultencoding()
est volontairement supprimé dusys
démarrage de Python. Le réactiver et changer le codage par défaut peut casser le code qui repose sur ASCII comme valeur par défaut (ce code peut être tiers, ce qui rendrait généralement sa résolution impossible ou dangereuse).la source
LC_CTYPE
(ou dans une application, de vérifier si elle est définie correctement et d'abandonner avec un message d'erreur significatif).LC_CTYPE=C python -c 'import locale; print( locale.getpreferredencoding())'
Si vous obtenez cette erreur lorsque vous essayez de diriger / rediriger la sortie de votre script
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
Exportez simplement PYTHONIOENCODING dans la console, puis exécutez votre code.
export PYTHONIOENCODING=utf8
la source
LC_CTYPE
plutôt quelque chose de sensé. Cela fait également plaisir à tous les autres programmes.PYTHONIOENCODING=utf8
n'est pas la valeur par défaut. Cela rend les scripts cassés juste parce queLC_ALL=C
Set LC_CTYPE to something sensible instead
C'est une suggestion raisonnable. Cela ne fonctionne pas très bien lorsque vous essayez de distribuer du code qui fonctionne uniquement sur le système d'une autre personne.C.utf8
locale pour fournir des paramètres régionaux plus intelligents. C. glibc en amont travaille à l'ajouter, alors peut-être ne devrions-nous pas blâmer Python pour le respect des paramètres régionaux \…?A) Pour contrôler la
sys.getdefaultencoding()
sortie:ascii
ensuite
et
utf-16-be
Vous pouvez placer votre sitecustomize.py plus haut dans votre
PYTHONPATH
.Vous aimerez peut-être aussi essayer
reload(sys).setdefaultencoding
par @EOLB) Pour contrôler
stdin.encoding
et questdout.encoding
vous souhaitez définirPYTHONIOENCODING
:ascii ascii
ensuite
utf-16-be utf-16-be
Enfin: vous pouvez utiliser A) ou B) ou les deux!
la source
from __future__ import unicode_literals
voir la discussionA partir de PyDev 3.4.1, l'encodage par défaut n'est pas changé plus. Voir ce ticket pour plus de détails.
Pour les versions antérieures, une solution consiste à s'assurer que PyDev ne fonctionne pas avec UTF-8 comme codage par défaut. Sous Eclipse, exécutez les paramètres de la boîte de dialogue ("exécuter les configurations", si je me souviens bien); vous pouvez choisir l'encodage par défaut dans l'onglet commun. Changez-le en US-ASCII si vous voulez avoir ces erreurs «tôt» (en d'autres termes: dans votre environnement PyDev). Consultez également un article de blog original pour cette solution de contournement .
la source
En ce qui concerne python2 (et python2 uniquement), certaines des premières réponses reposent sur l'utilisation du hack suivant:
Il est déconseillé de l'utiliser (cochez ceci ou cela )
Dans mon cas, cela a un effet secondaire: j'utilise des notebooks ipython, et une fois que j'exécute le code, la fonction «print» ne fonctionne plus. Je suppose qu'il y aurait une solution à cela, mais je pense toujours que l'utilisation du hack ne devrait pas être la bonne option.
Après avoir essayé de nombreuses options, celle qui a fonctionné pour moi utilisait le même code dans le
sitecustomize.py
, où ce morceau de code est censé être . Après avoir évalué ce module, la fonction setdefaultencoding est supprimée de sys.La solution est donc d'ajouter au fichier
/usr/lib/python2.7/sitecustomize.py
le code:Lorsque j'utilise virtualenvwrapper, le fichier que j'édite est
~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py
.Et quand j'utilise avec des notebooks python et conda, c'est
~/anaconda2/lib/python2.7/sitecustomize.py
la source
Il y a un article de blog perspicace à ce sujet.
Voir https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/ .
Je paraphrase son contenu ci-dessous.
En python 2, qui n'était pas aussi fortement typé en ce qui concerne le codage des chaînes, vous pouviez effectuer des opérations sur des chaînes codées différemment et réussir. Par exemple, ce qui suit reviendrait
True
.Cela serait valable pour chaque chaîne (normale, sans préfixe) qui a été encodée
sys.getdefaultencoding()
, qui est par défautascii
, mais pas les autres.L'encodage par défaut était censé être modifié à l'échelle du système
site.py
, mais pas ailleurs. Les hacks (également présentés ici) pour le définir dans les modules utilisateur n'étaient que cela: des hacks, pas la solution.Python 3 a changé le codage système par défaut en utf-8 (lorsque LC_CTYPE est compatible avec unicode), mais le problème fondamental a été résolu avec l'exigence d'encoder explicitement les chaînes "octets" chaque fois qu'elles sont utilisées avec des chaînes unicode.
la source
Premièrement:
reload(sys)
et définir un encodage aléatoire par défaut uniquement en ce qui concerne la nécessité d'un flux de terminal de sortie est une mauvaise pratique.reload
change souvent les choses dans sys qui ont été mises en place en fonction de l'environnement - par exemple les flux sys.stdin / stdout, sys.excepthook, etc.Résolution du problème d'encodage sur stdout
La meilleure solution que je connaisse pour résoudre le problème de codage des
print
chaînes unicode et au-delà de l'asciistr
(par exemple à partir de littéraux) sur sys.stdout est: prendre soin d'un sys.stdout (objet de type fichier) qui est capable et éventuellement tolérant vis-à-vis des besoins:Quand
sys.stdout.encoding
estNone
pour une raison quelconque, ou inexistant, ou erronément faux ou "moins" que ce dont le terminal ou le flux stdout est réellement capable, alors essayez de fournir un.encoding
attribut correct . Enfin en le remplaçantsys.stdout & sys.stderr
par un objet de type fichier à traduire.Lorsque le terminal / flux ne peut toujours pas encoder tous les caractères Unicode, et que vous ne voulez pas les casser
print
juste à cause de cela, vous pouvez introduire un comportement d'encodage avec remplacement dans l'objet de type fichier à traduire.Voici un exemple:
Utilisation de littéraux de chaîne simples Beyond-ASCII dans le code Python 2/2 + 3
Je pense que la seule bonne raison de changer le codage par défaut global (en UTF-8 uniquement) concerne une décision de code source d' application - et non à cause de problèmes d'encodage de flux d'E / S: pour écrire des littéraux de chaîne au-delà de l'ascii dans le code sans être forcé pour toujours utiliser l'
u'string'
échappement de style unicode. Cela peut être fait de manière assez cohérente (malgré ce que dit l'article d' anonbadger ) en prenant soin d'une base de code source Python 2 ou Python 2 + 3 qui utilise de manière cohérente les littéraux de chaîne simple ascii ou UTF-8 - dans la mesure où ces chaînes sont potentiellement silencieuses. conversion unicode et se déplacer entre les modules ou potentiellement aller à stdout. Pour cela, préférez "# encoding: utf-8
"ou ascii (pas de déclaration). Changez ou supprimez des bibliothèques qui reposent encore de manière très stupide sur les erreurs de codage par défaut ascii au-delà de chr # 127 (ce qui est rare aujourd'hui).Et faites comme ceci au démarrage de l'application (et / ou via sitecustomize.py) en plus du
SmartStdout
schéma ci-dessus - sans utiliserreload(sys)
:De cette façon, les littéraux de chaîne et la plupart des opérations (à l'exception de l'itération de caractères) fonctionnent à l'aise sans penser à la conversion Unicode comme s'il n'y aurait que Python3. Les E / S de fichiers nécessitent bien sûr toujours une attention particulière concernant les encodages - comme c'est le cas en Python3.
Remarque: les chaînes plains sont ensuite implicitement converties de utf-8 en unicode
SmartStdout
avant d'être converties en flux de sortie enconding.la source
Voici l'approche que j'ai utilisée pour produire du code compatible avec python2 et python3 et qui produisait toujours une sortie utf8 . J'ai trouvé cette réponse ailleurs, mais je ne me souviens plus de la source.
Cette approche fonctionne en remplaçant
sys.stdout
par quelque chose qui ne ressemble pas tout à fait à un fichier (mais qui n'utilise toujours que des éléments de la bibliothèque standard). Cela peut bien causer des problèmes pour vos bibliothèques sous-jacentes, mais dans le cas simple où vous avez un bon contrôle sur la façon dont sys.stdout out est utilisé dans votre framework, cela peut être une approche raisonnable.la source
Cela a résolu le problème pour moi.
la source
C'est un hack rapide pour quiconque est (1) sur une plate-forme Windows (2) exécutant Python 2.7 et (3) ennuyé parce qu'un bon logiciel (c'est-à-dire, pas écrit par vous donc pas immédiatement un candidat pour encoder / décoder l'impression manœuvres) n'afficheront pas les «jolis caractères unicode» dans l'environnement IDLE (Pythonwin imprime unicode finement), par exemple, les symboles de logique du premier ordre que Stephan Boyer utilise dans la sortie de son prouveur pédagogique au premier ordre logique prouveur .
Je n'aimais pas l'idée de forcer un rechargement système et je ne pouvais pas faire en sorte que le système coopère avec la définition de variables d'environnement telles que PYTHONIOENCODING (essayé la variable d'environnement Windows directe et la déposer dans un sitecustomize.py dans des packages de site comme un liner = 'utf-8').
Donc, si vous êtes prêt à pirater votre chemin vers le succès, allez dans votre répertoire IDLE, généralement: "C: \ Python27 \ Lib \ idlelib" Localisez le fichier IOBinding.py. Faites une copie de ce fichier et stockez-le ailleurs afin de pouvoir revenir au comportement d'origine lorsque vous le souhaitez. Ouvrez le fichier dans idlelib avec un éditeur (par exemple, IDLE). Accédez à cette zone de code:
En d'autres termes, commentez la ligne de code d'origine après le ' try ' qui rendait la variable d'encodage égale à locale.getdefaultlocale (car cela vous donnera cp1252 dont vous ne voulez pas) et à la place, forcez-le brutalement à 'utf-8 '(en ajoutant la ligne' encoding = 'utf-8 ' comme indiqué).
Je crois que cela n'affecte que l'affichage IDLE sur stdout et non l'encodage utilisé pour les noms de fichiers, etc. (qui est obtenu dans le codage du système de fichiers antérieur). Si vous rencontrez un problème avec un autre code que vous exécutez dans IDLE ultérieurement, remplacez simplement le fichier IOBinding.py par le fichier d'origine non modifié.
la source
Vous pouvez modifier l'encodage de l'ensemble de votre système d'exploitation. Sur Ubuntu, vous pouvez le faire avec
la source