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'ascii str
(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
est None
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çant sys.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:
#!/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 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 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 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.