D'abord : reload(sys)
et la définition d'un encodage par défaut aléatoire pour le seul besoin d'un flux terminal de sortie est une mauvaise pratique. reload
modifie souvent des 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ésoudre le problème de l'encodage sur stdout
La meilleure solution que je connaisse pour résoudre le problème d'encodage de print
dans les chaînes unicode et au-delà de l'ascii str
(par exemple, à partir de littéraux) sur sys.stdout est de prendre soin d'un sys.stdout (objet de type fichier) qui est capable et éventuellement tolérant en ce qui concerne les besoins :
-
Lorsque sys.stdout.encoding
est None
pour une raison quelconque, ou inexistante, ou erronée ou "inférieure" à ce que le terminal ou le flux stdout est réellement capable de faire, alors essayez de fournir un .encoding
attribut. Enfin, en remplaçant sys.stdout & sys.stderr
par un objet de type fichier de traduction.
-
Lorsque le terminal / flux ne peut toujours pas encoder tous les caractères unicode qui apparaissent, et lorsque vous ne voulez pas casser print
C'est justement à cause de cela que vous pouvez introduire un comportement d'encodage avec remplacement dans l'objet de type fichier de traduction.
Voici un exemple :
#!/usr/bin/env python
# encoding: utf-8
import sys
class SmartStdout:
def __init__(self, encoding=None, org_stdout=None):
if org_stdout is None:
org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout)
self.org_stdout = org_stdout
self.encoding = encoding or \
getattr(org_stdout, 'encoding', None) or 'utf-8'
def write(self, s):
self.org_stdout.write(s.encode(self.encoding, 'backslashreplace'))
def __getattr__(self, name):
return getattr(self.org_stdout, name)
if __name__ == '__main__':
if sys.stdout.isatty():
sys.stdout = sys.stderr = SmartStdout()
us = u'aouäöü'
print us
sys.stdout.flush()
Utilisation de chaînes de caractères simples au-delà de l'ascii dans le code Python 2 / 2 + 3
La seule bonne raison de changer l'encodage global par défaut (en UTF-8 uniquement) concerne, je pense, une application code source et non à cause de problèmes d'encodage de flux d'E/S : Pour écrire des chaînes de caractères au-delà de l'ascii dans le code sans être obligé de toujours utiliser u'string'
unicode style escaping. Cela peut être fait de manière assez cohérente (malgré ce que disent les auteurs de anonbadger (voir l'article de l'auteur) en s'occupant d'une base de code source Python 2 ou Python 2 + 3 qui utilise de manière cohérente les chaînes de caractères ascii ou UTF-8 - dans la mesure où ces chaînes de caractères peuvent subir une conversion unicode silencieuse et se déplacer entre les modules ou aller vers stdout. Pour cela, préférez " # encoding: utf-8
" ou ascii (pas de déclaration). Modifier ou abandonner les bibliothèques qui dépendent encore de manière très stupide et fatale des erreurs d'encodage 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 de l'option SmartStdout
ci-dessus - sans utiliser reload(sys)
:
...
def set_defaultencoding_globally(encoding='utf-8'):
assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding)
import imp
_sys_org = imp.load_dynamic('_sys_org', 'sys')
_sys_org.setdefaultencoding(encoding)
if __name__ == '__main__':
sys.stdout = sys.stderr = SmartStdout()
set_defaultencoding_globally('utf-8')
s = 'aouäöü'
print s
De cette façon, les chaînes de caractères et la plupart des opérations (à l'exception de l'itération des caractères) fonctionnent confortablement sans avoir à se soucier de la conversion unicode, comme s'il n'y avait que Python3. Les entrées/sorties de fichiers nécessitent bien sûr toujours une attention particulière en ce qui concerne les encodages - comme c'est le cas dans Python3.
Note : les chaînes plains sont ensuite implicitement converties de l'utf-8 à l'unicode en SmartStdout
avant d'être converti en encodage du flux de sortie.
1 votes
Voir l'article de blog L'Illusoire setdefaultencoding .
3 votes
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 ne jamais oublier de le faire / d'utiliser systématiquement votre propre interface. D'après mon expérience, cela devient très problématique lorsque vous écrivez du code que vous voulez faire fonctionner à la fois avec python2 et python3.