Dangers du sys.setdefaultencoding('utf-8')
Il y a une tendance à décourager la configuration sys.setdefaultencoding('utf-8')
en Python 2. Quelqu'un peut-il la liste des exemples concrets de problèmes avec ça? Des Arguments comme it is harmful
ou it hides bugs
n'est pas très convaincante.
Mise à JOUR: Veuillez noter que cette question n'est que d'environ utf-8
, il n'est pas sur la modification de codage par défaut "dans le cas général".
Veuillez donner quelques exemples avec le code si vous le pouvez.
- comment voulez-vous l'utiliser? Si vous parlez de la modification de sitecustomize.py ensuite, lorsque le code est exécuté sur d'autres ordinateurs, vous pourriez bien avoir des bugs
- Si vous avez une décoder ou encoder erreur c'est probablement pour une raison évidente, je.e
s = u'é' str(s)
. Vous devez travailler avec un type string ou unicode et de gérer l'encodage explicite. - stackoverflow.com/questions/28642781/..., pas de paramètres globaux - application seule.
- peut-être pertinent mail.python.org/pipermail/python-dev/2009-August/091406.html Vous pouvez obtenir des effets bizarres causé par le fait que certains objets string allons maintenant comparer l'égalité ne sont pas nécessairement avoir la même valeur de hachage. Unicode objets et les chaînes de caractères ont la même valeur de hachage pour autant qu'ils sont à la fois ASCII. Avec l'ASCII codage par défaut, un non-ASCII chaîne ne peut pas être comparé à un objet Unicode, donc le problème ne se produit pas.
UTF-8
chaîne n'est pas un objet Unicode encore, et quel que soit le codage de ces objets string ne se comparent égales si elles ont un contenu différent. Sauf si il y a un bug dans Python fonction de hachage,- Parce que vous êtes l'incompréhension comment Python fonctionne avec des encodages si vous pensez que vous en avez besoin. Voici une présentation de comment l'utiliser correctement: farmdev.com/talks/unicode – Que d'un côté, si l'argument “il se cache bugs” ne semble pas convaincant, que peut-être le véritable problème. (Et oui, Unicode Python 2 suce. Mais
sys.setdefaultencoding
n'est pas la solution.) Et enfin, si vous voulez voir un bug, il provoque, ne cherchez pas plus loin: stackoverflow.com/a/28627705/1968 - c'est pourquoi je demande un exemple réel que je peux comprendre.
- voici un exemple d'une question lorsqu'un utilisateur a vissé parce que l'Auteur de PyDev pense que c'est une bonne idée de mettre en
sys.setdefaultencoding('utf-8')
. Voici un blog de quelqu'un d'autre qui a vissé par cette avec quelques détails de plus en plus de liens. - Une belle annonce aujourd'hui sur le sujet: anonbadger.wordpress.com/2015/06/16/...
Vous devez vous connecter pour publier un commentaire.
L'affiche originale a demandé de code qui montre que l'interrupteur est dangereux—sauf qu'il "cache" bugs sans rapport avec le commutateur.
Résumé des conclusions
Basé à la fois sur l'expérience et des données que j'ai recueillies, voici les conclusions auxquelles je suis arrivé au.
Réglage de la defaultencoding de l'UTF-8 de nos jours est sûr, sauf pour des applications spécialisées, manipulation de fichiers non unicode prêt systèmes.
"Officiel" rejet de l'interrupteur est basé sur des raisons qui ne sont plus pertinentes pour une grande majorité d'utilisateurs (pas de bibliothèque fournisseurs), de sorte que nous devrions cesser de décourager les utilisateurs à définir.
De travail dans un modèle qui gère l'Unicode correctement par défaut est de loin mieux adapté pour les applications de la inter-systèmes de communications que manuellement travailler avec unicode Api.
Effectivement, la modification de l'encodage par défaut très fréquemment évite un certain nombre de l'utilisateur maux de tête dans la grande majorité des cas d'utilisation. Oui, il existe des situations dans lesquelles les programmes d'encodages multiples silencieusement se conduisent mal, mais depuis ce commutateur peut être activé de façon fragmentaire, c'est pas un problème dans le code de l'utilisateur.
Plus important encore, l'activation de ce drapeau est un réel avantage est des utilisateurs de code, à la fois par la réduction de la surcharge d'avoir à gérer manuellement conversions Unicode, encombrer le code et de le rendre moins lisible, mais aussi en évitant les éventuels bugs lorsque le programmeur ne parvient pas à le faire correctement dans tous les cas.
Étant donné que ces revendications sont à peu près l'exact opposé de Python ligne officielle de la communication, je pense que l'une des explications de ces conclusions est justifiée.
Exemples de succès en utilisant une version modifiée de defaultencoding dans la nature
Dave Malcom de Fedora pense que c'est toujours droit. Il a proposé, après avoir enquêté sur les risques, l'évolution de la distribution à l'échelle def.enc.=UTF-8 pour tous les utilisateurs de Fedora.
Dur fait présenté si pourquoi Python serait pause n'est que le hachage de comportement je répertorié, qui n'est jamais repris par tout autre adversaire dans le noyau de la communauté, comme une raison de s'inquiéter ou même par le même personne, lorsque l'on travaille sur de l'utilisateur de billets.
Résumé de Fedora: Certes, le changement lui-même a été décrit comme "follement impopulaire" avec les développeurs, et il a été accusé d'être incompatible avec les versions précédentes.
Il y a 3000 de projets à l'openhub de le faire. Ils ont une recherche lente frontend, mais la numérisation sur elle, j'estime à 98% l'utilisation de l'UTF-8. Rien trouvé sur de mauvaises surprises.
Il y a 18000(!) github maître branches avec elle changé.
Alors que le changement est "impopulaire" au cœur de la communauté assez populaires dans la base des utilisateurs. Bien que cela puisse être écartée, puisque les utilisateurs sont connus pour utiliser des hacky solutions, je ne pense pas que c'est un argument pertinent en raison de mon prochain point.
Il y a seulement 150 bugreports total sur GitHub à cause de cela. À un taux de manière efficace à 100%, le changement semble être positive, et non négative.
Pour résumer les problèmes existants personnes ont courir dans les, j'ai scanné par le biais de toutes ces billets.
Chaging def.enc. UTF-8 est généralement introduit mais pas supprimé la question d'un processus de clôture, le plus souvent comme une solution. Certains plus grands excuser comme correctif temporaire, compte tenu de la "mauvaise presse" il a, mais beaucoup plus de bug, les journalistes justeheureux sur le correctif.
Un peu (1 à 5?) les projets de modification de leur code à faire les conversions de type manuellement de sorte qu'ils n'ont pas besoin de changer la valeur par défaut plus.
Dans les deux cas je vois quelqu'un qui prétend qu'avec def.enc. ensemble de l'UTF-8 conduit à une absence totale de sortie entièrement, sans en expliquer la configuration de test. Je ne pouvais pas vérifier cette affirmation, et j'ai testé un et a trouvé le contraire pour être vrai.
Un les réclamations son "système" peut dépendre de ne pas changer, mais nous n'apprenons pas pourquoi.
(Et seulement) avait une vraie raison pour l'éviter: ipython utilise soit un 3ème partie module ou le test runner modifié leurs processus de manière incontrôlée (il n'est jamais contesté que le def.enc. le changement est préconisé par son promoteurs seulement à l'interprète de temps d'installation, c'est à dire lorsque les "posséder" le processus).
J'ai trouvé l'indication zéro que les différentes valeurs de hachage de 'é' et u é' provoque des problèmes dans le monde réel code.
Python n' pas "pause"
Après avoir modifié le réglage de l'UTF-8, pas de fonctionnalité de Python couverts par les tests unitaires est de travailler différemment, sans le commutateur. Le commutateur lui-même, cependant, n'est pas testé du tout.
Il est conseillé sur les bugs.python.org aux frustrations des utilisateurs
Exemples ici, ici ou ici
(souvent en rapport avec la ligne officielle de l'avertissement)
Le premier montre comment établi que l'interrupteur est en Asie (comparer aussi avec le github de l'argumentation).
Ian Bicking publié son soutien pour toujours l'activation de ce comportement.
Martijn Fassen, tout en réfutant Ian, admis que ASCII pourrait avoir été mal dans la première place.
En Python3, ils ne sont pas en pratique ce qu'ils prêchent"
Tout en s'opposant à toute définition.enc. changement si durement en raison de l'environnement code dépendant désire, une discussion ici tourne Python3's des problèmes avec ses "unicode sandwich" paradigme et le correspondant tenu des hypothèses implicites.
En outre, ils ont créé des possibilités pour écrire valide Python3-code comme:
DiveIntoPython le recommande.
Dans ce fil, Guido lui-même conseille un professionnel de l'utilisateur final utiliser un processus spécifique environt avec le commutateur à "créer un environnement Python pour chaque projet."
Jython propose de le changer à la volée, même dans des modules.
PyPy a pas support de rechargement(sys) - mais il ramena sur la demande de l'utilisateur au sein d'un seul jour sans se poser de questions. Comparer avec la "vous le faites mal" attitude de Disponible, revendiquant sans preuve c'est la "racine du mal".
Fin de cette liste, je confirme que l'on pourrait construire un module qui se bloque parce que de changement d'interprète de config, de faire quelque chose comme ceci:
Je ne pense pas que ce soit un argument valable, car la personne qui a écrit ce double type d'accepter module était évidemment au courant au sujet de l'ASCII et non des chaînes ASCII et serait au courant de l'encodage et du décodage.
Je pense que cette preuve est plus d'une indication suffisante que la modification de ce paramètre ne conduisent pas à des problèmes dans le monde réel des bases de codes la vaste majorité du temps.
goto
. Bien sûr, vous pouvez le faire fonctionner, mais vous aurez un moment plus difficile pour elle que vous développez l'application. Vous obtenez d'être incohérent dans votre gestion de l'Unicode et que va vous mordre. La plupart des gens qui l'utilisent ne pas comprendre Unicode et pense que c'est le chemin le plus facile.super()
. Généralement parlant, c'est un de Culte du Cargo, appliquée appliquée sans comprendre comment ça marche ou si elle est nécessaire à tous.setdefaultencoding
semble être plutôt un moyen sûr. Si quelque chose allait se briser grand moment, n'aurions nous pas entendu parler de cela maintenant, et ne pas dire chose qui se brise sur l'aide d'un autre encodage par défaut doit être corrigé? Merci pour votre perspicacité. IMO la façon Python 2.x continue de refuser de traiter ASCII > 127 par défaut est plutôt des arcanes (même si je suis entièrement en faveur de Python contraire)...sometext'.decode('whatever')
, et de ne pas soutenir la modification de la defaultenconding à mon humble avis est l'équivalent de dire que nous ne sommes pas sûr de savoir si le support de l'unicode fonctionne réellement [dans la stdlib]. De toute façon je obtenir votre point de vue. Essentiellement, cela signifie commutation defaultencoding n'est pas officiellement pris en charge, cependant, comme cela répond souligne, dans certaines circonstances, il y a des avantages à le faire. Merci pour votre POV.Parce que vous n'avez pas toujours voulez avoir vos chaînes automatiquement décodé en Unicode, ou de votre Unicode objets automatiquement encodée à octets. Puisque vous demandez un exemple concret, voici un:
Prendre un WSGI application web; vous êtes la construction d'une réponse par l'ajout du produit d'un processus externe d'une liste, dans une boucle, et que ce processus externe, vous donne codé en UTF-8 octets:
Qui est grande et fine et travaille. Mais alors, votre co-travailleur de la vient le long, et ajoute une nouvelle fonctionnalité, vous êtes en train de fournir des étiquettes de trop, et ceux-ci sont localisés:
- Vous testé cette en anglais et tout fonctionne toujours bien!
Cependant, la
translations.get_label()
bibliothèque renvoie en fait valeurs Unicode et lorsque vous changez les paramètres régionaux, les étiquettes contiennent des caractères non-ASCII.Le WSGI bibliothèque de écrit ces résultats à la prise, et toutes les valeurs Unicode obtenir l'auto-encodé pour vous, depuis que vous avez établi
setdefaultencoding()
en UTF-8, mais la longueur que vous avez calculé est tout à fait tort. Il va être trop court en UTF-8 code de tout à l'extérieur de la plage ASCII avec plus d'un octet.Tout cela, c'est ignorer la possibilité que vous êtes vraiment en train de travailler avec les données dans un codec différent; vous pourriez être l'écriture latine-1 + Unicode, et maintenant vous avez une mauvaise longueur de l'en-tête et un mélange de données encodages.
Vous avais pas utilisé
sys.setdefaultencoding()
une exception aurait été soulevées et vous saviez que vous aviez un bug, mais maintenant, vos clients se plaignent de réponses incomplètes; il y a des octets manquants à la fin de la page, et vous ne sais pas trop comment c'est arrivé.Noter que ce scénario n'est même pas impliquer 3ème partie les bibliothèques qui peut ou peut ne pas dépendre de la valeur par défaut étant toujours ASCII. Le
sys.setdefaultencoding()
paramètre est mondiale, s'appliquant à la tous l'exécution de code dans l'interpréteur. Comment êtes-vous sûr il n'y a pas de questions dans les bibliothèques impliquant implicite de codage et de décodage?Que Python 2 encode et décode entre
str
etunicode
types implicitement peuvent être utiles et en sécurité lorsque vous travaillez avec des données ASCII uniquement. Mais vous avez vraiment besoin de savoir lorsque vous mélangez Unicode et une chaîne d'octets de données accidentellement, plutôt que de mettre du plâtre avec un pinceau et de l'espoir pour le meilleur.you don't always want to have your strings automatically decoded to Unicode
- les cordes sont décodés en UTF-8, pas en Unicode objets.str + unicode
vous donneunicode
, à condition que lestr
pourrait être décodé.translations.get_label()
retourneunicode
objets. Le WSGI mise en œuvre pourrait aussi choisir de simplement concaténer tous les résultats, à quel point vous obtiendrez ununicode
objet de sortie transmis à la prise, ou peut-être à un autre WSGI d'emballage étiquette. Nous ne le savons pas, car nous taire toutes Python exceptions qui, normalement, auraient été jetés.sys.setdefaultencoding("utf-8")
Python va commencer la production deunicode
des objets dans des endroits où il a étéstr
précédemment. Est ce que le droit? (Je suis toujours à la lecture par le biais de l'exemple)str
objets lors de la concaténation avecunicode
objets, oui, et qui échoue si ces octets ne sont pas décodable ASCII. Mais dès que vous changez le codec par défaut, puis octets qui sont décodable en UTF-8 sera également converti et vous vous retrouvez avec Unicode objets où vous pensiez que vous avez été la production de valeurs d'octets au lieu de cela.sys.setdefaultencoding("utf-8")
. Je ne vois comment ce comportement est mauvais pour votre exemple. Dans le cas de mon application (Roundup) c'est à proximité de l'accident, je suis en train de fix - stackoverflow.com/questions/28642781/...sys.setdefaultencoding("utf-8")
est la seule recommandée moyen de corriger ça crash. Ce que j'entends de vous, c'est que le crash est le comportement souhaité. Je ne peux pas d'accord, désolé.the length you calculated is entirely wrong
est un bon argument. pastebin.ubuntu.com/10791721 donne 3 et 6 de la console. Mais cela ressemble à un bug en Python, qui est incapable de gérer les mutibyte encodages.sys.setdefaultencoding()
appel.len()
pour la chaîne de traitement, nous sommes fondamentalement enregistrer pour utilisersys.setdefaultencoding("utf-8")
(ce qui semble être le cas avec Roundup de base qui semble ne font que déplacer des chaînes utf-8 contenu de DB de la couche de modèle).utf-8
chaîne de traitement. Qui mène à la question stackoverflow.com/questions/29586776/... - comment tracer que des chaînes utf-8 sont passés à libs externes.unicode
au point d'entrée le plus tôt possible, et seulement coder d'octets au point de sortie, le plus tard possible. Dans ce contexte, je vous recommande de lire / voir Ned Batchelder du Pragmatique Unicode présentation.str
quelque part. Merci pour l'explication éclairante.Tout d'abord: de Nombreux adversaires de l'évolution de défaut enc faire valoir que son stupide, parce que son même en changeant ascii comparaisons
Je pense que c'est juste pour faire comprendre que, conformes à la question d'origine, je vois que personne ne préconisent rien d'autre que de s'écartant de l'Ascii vers UTF-8.
La setdefaultencoding('utf-16') exemple semble être toujours mis en avant par ceux qui s'opposent à changer 😉
Avec m = {'a': 1, 'é': 2} et le fichier 'out.py':
Alors:
[*]: Résultat suppose la même é. Voir ci-dessous sur ce.
En regardant ces opérations, la modification de l'encodage par défaut dans votre programme ne pourrait pas l'air trop mauvais, vous donnant des résultats "plus proche" d'avoir Ascii uniquement des données.
Concernant le hachage () et len() le comportement que vous obtenez la même chose, alors en Ascii (en savoir plus sur les résultats ci-dessous). Ces opérations montrent également qu'il existe d'importantes différences entre unicode et les chaînes d'octets qui pourrait provoquer des erreurs logiques, s'il est ignoré par vous.
Comme on l'a déjà vu: C'est un processus à l'échelle option si vous avez juste un coup de choisir ce qui est la raison pour laquelle bibliothèque les développeurs devraient vraiment de ne plus jamais le faire, mais obtenir leurs internes afin de sorte qu'ils n'ont pas besoin de compter sur python conversions implicites.
Ils ont également besoin de documenter clairement ce qu'ils attendent et de retour et de refuser l'entrée qu'ils n'ont pas écrit la lib (comme la fonction normaliser, voir ci-dessous).
=> Écrire des programmes avec ce paramètre sur fait-il risqué pour les autres à utiliser les modules de votre programme dans leur code, au moins sans filtrage d'entrée.
Remarque: Certains opposants affirment que le def.enc. c'est même un système à l'échelle de l'option (via sitecustomize.py), mais plus tard dans les moments de logiciels de la conteneurisation (menu fixe) chaque processus peut être commencé dans un environnement idéal w/o frais généraux.
Concernant le hachage et len() comportement:
Il vous dit que même une modification de la def.enc. vous ne pouvez pas toujours être ignorant sur les types de chaînes que vous traitez dans votre programme. u" et " sont différentes séquences d'octets dans la mémoire - pas toujours, mais en général.
Donc lors de l'essai assurez-vous que votre programme fonctionne correctement aussi avec les données Ascii.
Certains disent que le fait que les hachages peut devenir inégale lorsque les données de la modification des valeurs - bien qu'en raison de conversions implicites le '==' activités demeurent égaux - est un argument contre un changement de def.enc.
Personnellement, je ne partage pas que, depuis le hachage le comportement reste le même que w/o de le changer. Encore un exemple convaincant de comportements indésirables en raison de ce paramètre dans un processus de I 'propre'.
Dans l'ensemble, concernant setdefaultencoding("utf-8"): La réponse quant à si le son muet ou pas devrait être plus équilibré.
Il dépend.
Alors que c'est à éviter les collisions par exemple, à la str() opérations dans un journal de l'instruction, le prix est une chance plus élevée pour des résultats inattendus, plus tard, puisque le mauvais types en faire plus dans le code, dont le bon fonctionnement dépend d'un certain type.
En aucun cas, il devrait être l'alternative à l'apprentissage de la différence entre les chaînes d'octets et des chaînes unicode pour votre propre code.
Enfin, le paramètre de codage par défaut, loin de l'Ascii ne permet pas de rendre votre vie plus facile pour la commune de texte opérations comme len(), de tranchage et de comparaisons - devrait-on supposer que (byte)stringyfying le tout avec de l'UTF-8 sur résout les problèmes ici.
Malheureusement il n'a pas - en général.
Le '==' et len() les résultats sont loin problème plus complexe qu'on pourrait le penser - mais même avec la même type sur les deux côtés.
W/o def.enc. changé "==" ne parvient pas toujours à des fins non Ascii, comme indiqué dans le tableau. Avec elle, il fonctionne, parfois:
Unicode ne s'uniformiser autour d'un million de symboles du monde et leur a donné un certain nombre - mais il n'est malheureusement PAS un rapport de 1:1 bijection entre les glyphes affiché à l'utilisateur dans les périphériques de sortie et les symboles qu'ils sont générés à partir de.
Pour vous motiver la recherche de cette: le fait d'Avoir deux fichiers, j1, j2, écrit avec la même programme en utilisant le même encodage, contenant la saisie de l'utilisateur:
Résultat: 2.7.9 José José Faux (!)
À l'aide de l'impression en fonction de Py2 vous voyez la raison: Malheureusement, il y a DEUX façons de coder le même caractère, les caractères accentués 'e':
Ce qu'un stupide codec direz-vous mais ce n'est pas la faute de la codec. C'est un problème dans unicode en tant que tel.
De sorte que même dans Py3:
Résultat: 3.4.2 José José Faux (!)
=> Indépendant de Py2 et Py3, réellement indépendant de tout langage de calcul que vous utilisez Pour écrire un logiciel de qualité, vous avez probablement de "normaliser" toutes les entrées utilisateur. Le standard unicode ne standardiser la normalisation.
En Python 2 et 3 de la unicodedata.normaliser la fonction est votre ami.
setdefaultencoding()
béquille à tous?sys.setdefaultencoding()
doit être évitée.Réel exemple #1
Il ne fonctionne pas dans tests unitaires.
Le test runner (
nose
,py.test
, ...) initialisesys
d'abord, et ensuite seulement les découvre et les importations de vos modules. En ce moment c'est trop tard pour changer de codage par défaut.Par la même vertu, il ne fonctionne pas si quelqu'un exécute votre code dans un module, comme leur initialisation vient en premier.
Et oui, le mélange
str
etunicode
et en s'appuyant sur la conversion implicite seulement la pousse davantage le problème en bas de la ligne.sys.defaultencoding('utf-8')
, alors pourquoi ça ne marche pas?sys.defaultencoding('utf-8')
ne fonctionne pas si quelqu'un s'exécute en tant que module?sys.defaultencoding('utf-8')
. Aussi, sachez que je UTF-8 est essentiel, pour cette question, et il est rétro-compatible avec l'ASCII.sys.setdefaultencoding()
ne définit pas d'entrée ou de sortie de l'encodage; je pense que vous avez mal compris ce que la fonction t. Il définit le codec utilisé lors de la implicitement encodageunicode
àstr
ou de décodagestr
àunicode
lors du mélange des genres.sys
. Lorsque votre module fonctionne, il est trop tard pour changer l'encodage. Disponible hacks sontsitecustomize.py
etreload(sys)
. La précédente ne fonctionne pas avec les tests unitaires et n'est pas modulable. Le dernier est de la magie noire, vous êtes sur votre propre.Une chose que nous devons savoir est
donc, si nous changeons de codage par défaut, il y aura toutes sortes de questions incompatibles. par exemple:
Plus d'exemples:
Cela dit, je me souviens il y a quelques blog ce qui suggère l'utilisation de l'unicode chaque fois que possible, et la seule chaîne de bits lors de l'affaire I/O. je pense que si votre suivi de cette convention, la vie sera beaucoup plus facile. Plusieurs solutions peuvent être trouvées:
==
opérateur u-cordes de sorte qu'ils ont toujours sortie avec une erreur lors de la conversion implicite comme cela se produit?sys.setdefaultencoding("utf-8")
tout le temps, afin de faire"你好" == u"你好"
commeTrue
ce qui est correct3 == 3.0
est égalementTrue
. Equaliity est une déclaration sur l'information elle-même et non pas sur ce qui type de données, il est enveloppée dans de la.>>> print "abc" == u"abc" => True
>>> print "你bc" == u"你bc" => False
...sont les mêmes qui, dans leur unicode sandwich idée, d'accepter un silencieuxdecode('utf-8')
dans à peu près TOUTES les I/O lib de Python3.sys.setdefaultencoding("utf-8")