J'exécute un système Linux récent où tous mes paramètres régionaux sont UTF-8:
LANG=de_DE.UTF-8
LANGUAGE=
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
...
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=
Maintenant, je veux écrire du contenu encodé en UTF-8 sur la console.
En ce moment Python utilise UTF-8 pour l’encodage FS mais s’en tient à ASCII pour l’encodage par défaut :
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.getfilesystemencoding()
'UTF-8'
Je pensais que la meilleure façon (propre) de faire cela était de définir la variable d'environnement PYTHONIOENCODING
. Mais il semble que Python l'ignore. Au moins sur mon système, je continue à obtenir ascii
comme encodage par défaut, même après avoir défini le envvar.
# tried this in ~/.bashrc and ~/.profile (also sourced them)
# and on the commandline before running python
export PYTHONIOENCODING=UTF-8
Si je fais ce qui suit au début d'un script, cela fonctionne bien:
>>> import sys
>>> reload(sys) # to enable `setdefaultencoding` again
<module 'sys' (built-in)>
>>> sys.setdefaultencoding("UTF-8")
>>> sys.getdefaultencoding()
'UTF-8'
Mais cette approche semble impure . Alors, quel est le bon moyen d'y parvenir?
Au lieu de changer l'encodage par défaut - ce qui est pas une bonne idée (voir la réponse de Mesilliac) - je viens juste d'envelopper sys.stdout
avec un StreamWriter
comme ceci:
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)
Voir --- (this Gist pour une petite fonction utilitaire, qui la gère.
Comment imprimer du texte encodé en UTF-8 sur la console sous Python <3?
print u"some unicode text \N{EURO SIGN}"
print b"some utf-8 encoded bytestring \xe2\x82\xac".decode('utf-8')
si vous avez une chaîne Unicode, imprimez-la directement. Si vous avez une chaîne d'octets, convertissez-la d'abord en Unicode.
Vos paramètres régionaux (LANG
, LC_CTYPE
) Indiquent des paramètres régionaux utf-8. Par conséquent, vous pouvez (en théorie) imprimer directement une chaîne bytest-utf-8 qui doit être affichée correctement dans votre terminal (si les paramètres du terminal sont cohérents avec les paramètres régionaux et ils devraient l'être), mais vous devez l'éviter: ne codez pas le codage de caractères de votre environnement dans votre script; affiche directement Unicode à la place.
Votre question comporte de nombreuses fausses hypothèses.
Vous n'avez pas besoin de définir PYTHONIOENCODING
avec vos paramètres régionaux pour imprimer Unicode sur le terminal. Le paramètre régional utf-8 prend en charge tous les caractères Unicode, c’est-à-dire qu’il fonctionne tel quel.
Vous n'avez pas besoin de la solution de contournement sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)
. Cela risque de se rompre si un code (que vous ne contrôlez pas) doit imprimer des octets et/ou s'il peut se rompre avec impression de la console Unicode sur Windows (page de code incorrecte, impossible d'imprimer des caractères indécodables) . Les paramètres régionaux corrects et/ou PYTHONIOENCODING
vvar sont suffisants. En outre, si vous devez remplacer sys.stdout
, Alors tilisez io.TextIOWrapper()
au lieu de codecs
module comme package win-unicode-console
fait.
sys.getdefaultencoding()
n'est pas lié à vos paramètres régionaux ni à PYTHONIOENCODING
. Votre hypothèse selon laquelle le réglage de PYTHONIOENCODING
devrait changer sys.getdefaultencoding()
est incorrecte. Vous devriez plutôt vérifier sys.stdout.encoding
.
sys.getdefaultencoding()
n'est pas utilisé lorsque vous imprimez sur la console. Il peut être utilisé comme solution de secours sur Python 2 si stdout est redirigé vers un fichier/canal à moins que PYTHOHIOENCODING
ne soit défini:
$ python2 -c'import sys; print(sys.stdout.encoding)'
UTF-8
$ python2 -c'import sys; print(sys.stdout.encoding)' | cat
None
$ PYTHONIOENCODING=utf8 python2 -c'import sys; print(sys.stdout.encoding)' | cat
utf8
N'appelez pas sys.setdefaultencoding("UTF-8")
; cela pourrait corrompre vos données silencieusement et/ou casser les modules tiers qui ne s'y attendaient pas. Rappelez-vous que sys.getdefaultencoding()
est utilisé pour convertir des chaînes d'octets (str
) en/de unicode
in Python 2 implicitement Par exemple, "a" + u"b"
. Voir aussi, la citation dans la réponse de @ mesilliac .
Il semble que cela ne soit pas recommandé.
Fedora a suggéré en utilisant les paramètres régionaux du système comme valeur par défaut , mais apparemment, cela casse d'autres choses.
Voici une citation de la discussion sur la liste de diffusion :
Les seuls encodages pris en charge par défaut dans Python sont: Python 2.x: ASCII Python 3.x: UTF-8 Si vous les modifiez, vous êtes seul et des choses étranges vont Commencer. L’encodage par défaut n’affecte pas seulement la traduction entre Python et le monde extérieur, mais également toutes les conversions internes entre les chaînes de 8 bits et Unicode. . Comme ce qui se passe dans le module pango (définir le codage par défaut de Sur "utf-8" en rechargeant le module de site dans Afin d'obtenir le Les API sys.setdefaultencoding () ne sont que tout à fait fausses et entraîneront de graves problèmes puisque les objets Unicode mettent en cache leur représentation codée par défaut. activez l'utilisation d'un codage par défaut basé sur les paramètres régionaux. Si tout ce que vous voulez, c'est obtenir les codages de stdout et stdin correctement configurés pour les canaux, vous devez inst ead changez l'attribut .encoding de ceux-ci (seulement). - Marc-André Lemburg eGenix.com
Voici comment je le fais:
#!/usr/bin/python2.7 -S
import sys
sys.setdefaultencoding("utf-8")
import site
Noter la -S
dans la ligne de démarcation. Cela indique à Python de ne pas importer automatiquement le module site
. Le module site
définit l’encodage par défaut et supprime la méthode afin qu’elle ne puisse pas être utilisée. à nouveau, mais honorera ce qui est déjà défini.
Si le programme n'affiche pas les caractères appropriés à l'écran, c'est-à-dire un symbole non valide, exécutez le programme à l'aide de la ligne de commande suivante:
PYTHONIOENCODING=utf8 python3 yourprogram.py
Ou, si votre programme est un module installé globalement:
PYTHONIOENCODING=utf8 yourprogram
Sur certaines plates-formes comme Cygwin (terminal mintty.exe
) Avec Anaconda Python
(ou Python 3
), Exécutez simplement export PYTHONIOENCODING=utf8
Et exécutez ultérieurement le programme ne fonctionne pas, et vous devez toujours faire à chaque fois PYTHONIOENCODING=utf8 yourprogram
pour exécuter le programme correctement.
Sous Linux, dans le cas de Sudo
, vous pouvez essayer de passer l'argument -E
Pour exporter les variables utilisateur vers le processus Sudo:
export PYTHONIOENCODING=utf8
Sudo -E python yourprogram.py
Si vous essayez ceci et que cela ne fonctionne pas, vous devrez entrer sur un shell Sudo:
Sudo /bin/bash
PYTHONIOENCODING=utf8 yourprogram
En relation: