Je développe une application multiplateforme pour Linux et Windows 7. Tous mes fichiers ont d'abord été écrits sous Linux et encodés en tant que utf-8
, mais lorsque j'ouvre ce même projet sous Windows, le fichier kv
est lu en utilisant l'encodage cp1252
. La même chose ne semble pas arriver à mes fichiers .py
peut-être parce que j'utilise python3.
En conséquence, les caractères Unicode écrits sur le fichier kv
ne seront pas rendus correctement sur l'application Kivy. La chaîne 'Título'
s'affichera sous la forme TÃ-tulo
.
Mes paramètres sont : Kivy=1.9.1, Python=3.4.4, Windows 7 x64 Home Premium.
De plus, mon python a été installé à l'aide d'Anaconda, mais cela n'a probablement aucun rapport.
Ecrire un fichier kv
encodé avec utf-8
:
# test.kv
<myButton@Button>:
text: 'Título'
Sur l'interpréteur python ou le script .py
:
import kivy
from kivy.lang import Builder
from kivy.uix.button import Button
Builder.load_file('test.kv')
class myButton(Button):
pass
print( myButton().text == 'Título' ) # False
print( myButton().text.encode('cp1252').decode() == 'Título' ) # True
La solution de contournement multiplateforme que j'ai trouvée était la suivante :
# test.kv
<myButton@Button>:
text: str(b'T\xc3\xadtulo'.decode())
Pour info, un moyen un peu plus simple de contourner ce problème consiste à utiliser des littéraux Unicode :
<MyButton@Button>:
text: u'T\u00edtulo'
Merci, je vais l'utiliser =)
Pour quelqu'un d'autre utilisant cette solution de contournement, si vous souhaitez trouver la séquence d'échappement Unicode pour votre caractère Unicode, vous pouvez la trouver comme ceci :
>> hex( ord('ã') )
0xe3
>> u'\u00e3'
'ã'
Ne pensez-vous pas qu'il devrait y avoir un meilleur moyen ? (en écoutant Hettinger parler...)
un en-tête # qui indiquerait comment le caractère unicode doit être géré ?
Même si cette astuce fonctionne... elle rend le texte très difficile à lire lorsqu'il y a beaucoup de caractères Unicode...
Est-ce seulement un bug de Windows ?
Eh bien, ce n'est pas une méthode recommandée pour gérer les encodages, mais vous pouvez l'utiliser. Cela a fonctionné pour moi dans py2.7 avec kivy 1.8.0, mais cela pourrait fonctionner même avec py3. Fichiers enregistrés en tant que utf-8
, symboles \u...
utilisés directement en tant que u'ä'
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Oui @ChristianTremblay , ce n'est qu'un bug de Windows. C'est en fait parce que l'encodage par défaut de Windows est cp1252, obligeant Kivy à lire le fichier .kv comme s'il était encodé de cette façon. Peut-être que la solution proposée par @KeyWeeUsr aide vraiment, je n'ai pas essayé cela, mais pourrait être plus propre que l'autre solution de contournement proposée.
Je suis d'accord, une bonne solution serait d'autoriser la spécification d'encodage sur le fichier .kv comme on peut le faire en python :
# -*- coding: utf-8 -*-
<MyWidget>:
# ...
Et si utf-8 était obligatoire pour les fichiers kv ?
def load_file(self, filename, **kwargs):
'''Insert a file into the language builder and return the root widget
(if defined) of the kv file.
:parameters:
`rulesonly`: bool, defaults to False
If True, the Builder will raise an exception if you have a root
widget inside the definition.
'''
filename = resource_find(filename) or filename
if __debug__:
trace('Builder: load file %s' % filename)
with open(filename, 'r', encoding='utf-8') as fd:
kwargs['filename'] = filename
data = fd.read()
# remove bom ?
if PY2:
if data.startswith((codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE)):
raise ValueError('Unsupported UTF16 for kv files.')
if data.startswith((codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE)):
raise ValueError('Unsupported UTF32 for kv files.')
if data.startswith(codecs.BOM_UTF8):
data = data[len(codecs.BOM_UTF8):]
return self.load_string(data, **kwargs)
Ceci se trouve dans kivy/lang/builder.py ligne 275 et plus
@ChristianTremblay , je pense que ce ne serait pas pour le mieux. Certains utilisateurs peuvent toujours utiliser des éditeurs de texte avec des encodages par défaut différents de « utf-8 », par exemple le codage Windows par défaut « cp1252 ». Nous devons fournir une solution pour les deux.
Le mieux serait probablement d'imiter le comportement de python :
Vous rencontrez un problème sur Android :
An unanticipated UnicodeDecodeError occurred: 'ascii' codec can't decode byte 0xef in position 564: ordinal not in range(128)
Traceback (most recent call last):
File "./pages.py", line 21, in <module>
Builder.load_file('pages.kv')
File "/data/data/.../files/app/crystax_python/site-packages/kivy/lang/builder.py", line 290, in load_file
data = fd.read()
File "/data/data/.../files/app/crystax_python/stdlib.zip/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 564: ordinal not in range(128)
((boggle)) Semble fonctionner sur ma machine Linux cependant.
La valeur par défaut devrait certainement être utf-8, mais pas forcée comme obligatoire.
mixmastamyk j'ai eu exactement le même problème.
Mon application fonctionne bien, mais lorsque je crée l'APK et que je l'exécute sur mon téléphone Android, j'obtiens :
UnicodeDecodeError : le codec 'ascii' ne peut pas décoder l'octet 0xc3 en position 352 : l'ordinal n'est pas dans la plage (128)
C'est parce que j'ai quelques "É" dans mon fichier. Dommage que je code en python3 pour éviter ce genre de choses ennuyeuses.
Droit. On dirait que Builder.load_file()
devrait par défaut être utf8 et/ou avoir un paramètre d'encodage. En attendant j'ai fait ça :
with open(filename, encoding='utf8') as f:
Builder.load_string(f.read())
Assurez-vous de désactiver le chargement automatique du fichier kv, sinon l'erreur sera toujours renvoyée et donnera l'impression que cela n'a pas fonctionné. Le formulaire '\u2026' peut également fonctionner s'il ne s'agit que d'un ou deux caractères.
Idée intelligente.merci !
Je vais essayer ça.
Ce problème a été automatiquement marqué comme obsolète car il n'a pas eu d'activité récente. Il sera fermé si aucune autre activité ne se produit. Merci pour vos contributions.
Comme c'est pratique, ignorez les bugs et laissez-les se fermer.
En fait, nous avons déterré d'anciens problèmes pour les trier, aucun problème valide et exploitable ne sera fermé. Bien que ce genre d'attitude n'aide pas à la motivation nécessaire pour consacrer nos après-midi au projet.
N'était pas irrité par le manque de travail mais plutôt par un bot qui ferme les problèmes ignorés. Celui-ci peut éventuellement prendre une ou deux lignes de code pour ajouter un paramètre d'encodage à load_file. Je l'aurais fait moi-même, mais il y a 70 demandes de tirage en attente.
Un projet avec peu de main-d'œuvre ne devrait pas avoir ce type de bot.
Je vous encourage quand même à faire cette pull request. S'il s'agit d'une solution claire et facile, elle a de bonnes chances d'être fusionnée.
J'ai le même problème avec kivy 1.10, mon application fonctionne parfaitement sur Linux avec python3 ( python3 main.py) mais lorsque je débogue le déploiement sur mon téléphone Android, l'application plante :/ très ennuyeux si vous voulez faire quelque chose avec de la qualité
Vous avez toujours ce problème avec kivy 1.10.1 et python 3.6.6 sous Windows 10. La solution de contournement actuelle consiste à ne pas charger automatiquement le fichier .kv. Renommez-le en quelque chose qui ne se charge pas par défaut, enregistrez-le avec l'encodage utf8 et procédez comme indiqué dans #5154
from kivy.lang import Builder
with open('MyApp.renamed.kv', encoding='utf8') as f:
Builder.load_string(f.read())
La solution
kivy 1.10.1 python 3.5.3 windows 7
même comportement sur windows 10 et python 3.6.5
Le même code fonctionne parfaitement sur osx et linux
EDIT : le problème est dans la directive de langue #:include
kv
La solution
Solution 1 : mettez tout votre code kv dans un seul fichier
Solution 2 :
for kvfile in ['file1.kv', 'file2.kv']:
with open(kvfile, encoding='utf8') as f:
Builder.load_string(f.read())
Eh bien, j'ai eu la même erreur avec des mots comme "Número" ou "veículo". J'ai essayé avec le code suivant :
from kivy.lang import Builder
with open('myApp.kv', encoding='utf8') as f:
Builder.load_string(f.read())
Mais j'ai eu un problème pour faire ça. Lorsque j'ai exécuté l'application, j'ai pu voir deux étiquettes différentes se chevaucher.
La solution consistait à enregistrer le fichier kv dans un sous-répertoire, puis à appeler le avec open comme ceci :
with open('./kvfile/myApp.kv', encoding='utf-8') as f:
Builder.load_string(f.read())
Le problème a été résolu car le chargement automatique ne trouvera pas le fichier kv dans le même répertoire que main.py. Cela ne dupliquera donc pas la visualisation.
@piontk Hé, je pensais que ce serait mon salut, mais quand je l'essaie, il dit que "l'encodage" n'est pas un paramètre valide pour "ouvrir". Pourquoi? (De plus, désolé si c'est une question stupide, c'est ma toute première application)
D'accord, je sais que ce n'est pas idéal, mais si aucune de ces options ne fonctionne pour vous, vous pouvez définir la chaîne souhaitée sur une variable dans la classe principale de l'application dans votre fichier .py, qui a un codage utf-8, puis y accéder dans votre fichier .kv.
#.py
class MainApp(App):
struser = ('Nome de usuário')
#.kv
Label:
text: app.struser
travaillé pour moi
Commentaire le plus utile
Oui @ChristianTremblay , ce n'est qu'un bug de Windows. C'est en fait parce que l'encodage par défaut de Windows est cp1252, obligeant Kivy à lire le fichier .kv comme s'il était encodé de cette façon. Peut-être que la solution proposée par @KeyWeeUsr aide vraiment, je n'ai pas essayé cela, mais pourrait être plus propre que l'autre solution de contournement proposée.
Je suis d'accord, une bonne solution serait d'autoriser la spécification d'encodage sur le fichier .kv comme on peut le faire en python :