Lors de la transmission de la sortie d'un programme Python, l'interpréteur Python est confus au sujet de l'encodage et le définit sur Aucun. Cela signifie un programme comme celui-ci:
# -*- coding: utf-8 -*-
print u"åäö"
fonctionnera correctement lorsqu'il est exécuté normalement, mais échouera avec:
UnicodeEncodeError: le codec 'ascii' ne peut pas coder le caractère u '\ xa0' en position 0: l'ordinal n'est pas dans la plage (128)
lorsqu'il est utilisé dans une séquence de tuyaux.
Quelle est la meilleure façon de faire fonctionner cela lors de la tuyauterie? Puis-je simplement lui dire d'utiliser l'encodage du shell / système de fichiers / tout ce qui est utilisé?
La suggestion que j'ai vue jusqu'à présent est de modifier directement votre site.py, ou de coder en dur le codage par défaut en utilisant ce hack:
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"
Existe-t-il une meilleure façon de faire fonctionner la tuyauterie?
chcp 65001
avant d'exécuter votre script. Cela peut avoir des problèmes, mais cela aide souvent et ne nécessite pas beaucoup de saisie (moins queset PYTHONIOENCODING=utf_8
).setx PYTHONENCODING utf-8
de le rendre permanent si vous souhaitez enregistrer la saisie.Réponses:
Votre code fonctionne lorsqu'il est exécuté dans un script car Python code la sortie dans le codage utilisé par votre application de terminal. Si vous canalisez, vous devez le coder vous-même.
Une règle d'or est la suivante: utilisez toujours Unicode en interne. Décodez ce que vous recevez et encodez ce que vous envoyez.
Un autre exemple didactique est un programme Python pour convertir entre ISO-8859-1 et UTF-8, mettant tout en majuscule entre les deux.
La définition du codage par défaut du système est une mauvaise idée, car certains modules et bibliothèques que vous utilisez peuvent s'appuyer sur le fait qu'il est ASCII. Ne le fais pas.
la source
sys.stdout
semble être une manière plus agréable.PYTHONIOENCODING
si vous redirigez laTout d'abord, concernant cette solution:
Il n'est pas pratique d'imprimer explicitement avec un encodage donné à chaque fois. Ce serait répétitif et sujet aux erreurs.
Une meilleure solution consiste à changer
sys.stdout
au début de votre programme, à encoder avec un encodage sélectionné. Voici une solution que j'ai trouvée sur Python: Comment est choisi sys.stdout.encoding? , en particulier un commentaire de "toka":la source
def myprint(unicodeobj): print unicodeobj.encode('utf-8')
- vous détectez automatiquement l'encodage du terminal en inspectantsys.stdout.encoding
, mais vous devez considérer le cas où il se trouveNone
(c'est-à-dire lors de la redirection de la sortie vers un fichier) vous avez donc besoin d'une fonction distincte de toute façon.Vous pouvez essayer de changer la variable d'environnement "PYTHONIOENCODING" en "utf_8". J'ai écrit une page sur mon calvaire avec ce problème .
Tl; dr de l'article de blog:
vous donne
la source
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
. Cela peut être fait à partir du programme python, donc l'utilisateur n'est pas obligé de définir une variable env.PYTHONIOENCODING
fonctionne. L'interprétation des octets en tant que texte est définie par l' environnement utilisateur . Votre script ne doit pas supposer et dicter à l'environnement utilisateur le codage de caractères à utiliser. Si Python ne récupère pas les paramètres automatiquement, vousPYTHONIOENCODING
pouvez le définir pour votre script. Vous ne devriez pas en avoir besoin à moins que la sortie ne soit redirigée vers un fichier / pipe.faire le travail, mais ne peut pas le définir sur python lui-même ...
ce que nous pouvons faire, c'est vérifier si le paramètre n'est pas défini et dire à l'utilisateur de le définir avant d'appeler le script avec:
Mise à jour pour répondre au commentaire: le problème existe juste lors du canalisation vers stdout. J'ai testé dans Fedora 25 Python 2.7.13
chat b.py
en cours d'exécution ./b.py
en cours d'exécution ./b.py | Moins
la source
sys.stdout.encoding
est automatiquement défini en fonction de laLC_CTYPE
valeur locale.J'ai eu un problème similaire la semaine dernière . C'était facile à corriger dans mon IDE (PyCharm).
Voici ma solution:
À partir de la barre de menus de PyCharm: Fichier -> Paramètres ... -> Éditeur -> Encodages de fichiers, puis définissez: "Encodage IDE", "Encodage de projet" et "Encodage par défaut pour les fichiers de propriétés" TOUS en UTF-8 et elle travaille maintenant comme un charme.
J'espère que cela t'aides!
la source
Une version aseptisée discutable de la réponse de Craig McQueen.
Usage:
la source
Je pourrais "l'automatiser" avec un appel à:
Oui, il est possible d'obtenir une boucle infinie ici si ce "setenv" échoue.
la source
Je pensais juste que je mentionnerais quelque chose ici que j'ai dû consacrer longtemps à expérimenter avant de finalement réaliser ce qui se passait. Cela peut être si évident pour tout le monde ici qu'ils n'ont pas pris la peine de le mentionner. Mais cela m'aurait aidé s'ils l'avaient fait, donc selon ce principe ...!
NB: J'utilise spécifiquement Jython , v 2.7, donc il est possible que cela ne s'applique pas à CPython ...
NB2: les deux premières lignes de mon fichier .py sont:
Le mécanisme de construction de chaîne "%" (AKA "opérateur d'interpolation") provoque également des problèmes ADDITIONNELS ... Si le codage par défaut de "l'environnement" est ASCII et que vous essayez de faire quelque chose comme
Vous n'aurez aucune difficulté à exécuter dans Eclipse ... Dans une CLI Windows (fenêtre DOS), vous constaterez que l'encodage est la page de codes 850 (mon système d'exploitation Windows 7) ou quelque chose de similaire, qui peut gérer au moins les caractères accentués européens, donc il va travailler.
fonctionnera également.
Si, OTOH, vous dirigez vers un fichier à partir de la CLI, l'encodage stdout sera None, qui sera par défaut ASCII (sur mon système d'exploitation de toute façon), qui ne pourra gérer aucune des impressions ci-dessus ... (encodage redouté Erreur).
Alors vous pourriez penser à rediriger votre stdout en utilisant
et essayez d'exécuter dans la tuyauterie CLI vers un fichier ... Très bizarrement, l'impression A ci-dessus fonctionnera ... Mais l'impression B ci-dessus générera l'erreur de codage! Cependant, les éléments suivants fonctionneront correctement:
La conclusion à laquelle je suis parvenu (provisoirement) est que si une chaîne qui est spécifiée pour être une chaîne Unicode utilisant le préfixe "u" est soumise au mécanisme de gestion%, elle semble impliquer l'utilisation du codage d'environnement par défaut, indépendamment de si vous avez défini stdout pour rediriger!
La façon dont les gens gèrent cela est une question de choix. Je souhaiterais la bienvenue à un expert Unicode pour dire pourquoi cela se produit, si je me trompe d'une manière ou d'une autre, quelle est la solution préférée à cela, si cela s'applique également à CPython , si cela se produit en Python 3, etc., etc.
la source
"fréd"
c'est une séquence d'octets et non une chaîne Unicode, donc lecodecs.getwriter
wrapper le laissera tranquille. Vous avez besoin d'un leaderu
, oufrom __future__ import unicode_literals
.J'ai rencontré ce problème dans une application héritée, et il était difficile d'identifier où ce qui était imprimé. Je me suis aidé avec ce hack:
En plus de mon script, test.py:
Notez que cela modifie TOUS les appels à imprimer pour utiliser un encodage, donc votre console imprimera ceci:
la source
Sous Windows, j'ai eu ce problème très souvent lors de l'exécution d'un code Python à partir d'un éditeur (comme Sublime Text), mais pas si vous l'exécutiez à partir de la ligne de commande.
Dans ce cas, vérifiez les paramètres de votre éditeur. Dans le cas de SublimeText, cela l'a
Python.sublime-build
résolu:la source