Kivy: Codierungsproblem bei der kv-Datei 'utf-8' unter Windows

Erstellt am 16. Feb. 2016  ·  24Kommentare  ·  Quelle: kivy/kivy

Ich entwickle eine plattformübergreifende App für Linux und Windows 7. Alle meine Dateien wurden zuerst unter Linux geschrieben und als utf-8 codiert, aber wenn ich dasselbe Projekt unter Windows öffne, wird die Datei kv angezeigt wird mit der Codierung cp1252 gelesen. Das Gleiche scheint mit meinen .py Dateien nicht zu passieren, vielleicht weil ich Python3 verwende.

Infolgedessen werden die Unicode-Zeichen, die in die kv Datei geschrieben werden, in der Kivy-App nicht richtig gerendert. Die Zeichenfolge 'Título' wird als TÃ-tulo .

Meine Einstellungen sind: Kivy=1.9.1, Python=3.4.4, Windows 7 x64 Home Premium.

Auch mein Python wurde mit Anaconda installiert, aber das hat wahrscheinlich nichts damit zu tun.

Um das Problem zu reproduzieren:

Schreiben Sie eine kv Datei, die mit utf-8 codiert ist:

# test.kv
<myButton@Button>:
    text: 'Título'

Auf Python-Interpreter oder .py Skript:

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

Die plattformübergreifende Problemumgehung, die ich gefunden habe, war diese:

# test.kv
<myButton@Button>:
    text: str(b'T\xc3\xadtulo'.decode())

Hilfreichster Kommentar

Ja @ChristianTremblay , dies ist nur ein Windows-Fehler. Dies liegt tatsächlich daran, dass die Windows-Standardcodierung cp1252 ist, was dazu führt, dass Kivy die .kv-Datei liest, als ob sie auf diese Weise codiert wäre. Vielleicht hilft die von @KeyWeeUsr vorgeschlagene Problemumgehung .

Ich stimme zu, eine gute Lösung wäre, die Kodierungsspezifikation für die .kv-Datei zuzulassen, wie wir es in Python tun können:

# -*- coding: utf-8 -*-
<MyWidget>:
    # ...

Alle 24 Kommentare

Zu Ihrer Information - eine etwas einfachere Möglichkeit, dies zu umgehen, besteht darin, Unicode-Literale zu verwenden:

<MyButton@Button>:
    text: u'T\u00edtulo'

Danke, das werde ich nutzen =)

Für jemand anderen, der diese Problemumgehung verwendet, wenn Sie die Unicode-Escape-Sequenz für Ihr Unicode-Zeichen finden möchten, finden Sie sie möglicherweise wie folgt:

>> hex( ord('ã') )
0xe3
>> u'\u00e3'
'ã'

Findest du nicht, dass es einen besseren Weg geben sollte? (Ohr Hettinger spricht...)

ein # Header , der sagt , wie das Unicode - Zeichen behandelt werden soll ?

Auch wenn dieser Trick funktioniert... er macht es wirklich schwer, Text zu lesen, wenn es viele Unicode-Zeichen gibt...

Ist das nur ein Windows-Bug?

Nun, dies ist keine empfohlene Methode zum Umgang mit Codierungen, aber Sie können diese verwenden. Es funktionierte für mich in py2.7 mit kivy 1.8.0, aber es könnte sogar mit py3 funktionieren. Als utf-8 gespeicherte Dateien, \u... Symbole werden direkt als u'ä'

    import sys
    reload(sys)
    sys.setdefaultencoding("utf-8")

Ja @ChristianTremblay , dies ist nur ein Windows-Fehler. Dies liegt tatsächlich daran, dass die Windows-Standardcodierung cp1252 ist, was dazu führt, dass Kivy die .kv-Datei liest, als ob sie auf diese Weise codiert wäre. Vielleicht hilft die von @KeyWeeUsr vorgeschlagene Problemumgehung .

Ich stimme zu, eine gute Lösung wäre, die Kodierungsspezifikation für die .kv-Datei zuzulassen, wie wir es in Python tun können:

# -*- coding: utf-8 -*-
<MyWidget>:
    # ...

Was wäre, wenn utf-8 für kv-Dateien obligatorisch wäre?

    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)

Dies ist in kivy/lang/builder.py Zeile 275 und höher zu finden

@ChristianTremblay , ich denke, das wäre nicht das Beste. Einige Benutzer verwenden möglicherweise immer noch Texteditoren mit anderen Standardcodierungen als 'utf-8', zum Beispiel die Standard-Windows-Codierung 'cp1252'. Für beides müssen wir eine Lösung bieten.

Das Beste wäre wahrscheinlich, das Verhalten von Python nachzuahmen:

  • Erwarten Sie, dass der Programmierer die Kodierung in der ersten Zeile angibt.
  • Oder verwenden Sie die Python-Standardcodierung (bei Python3 wäre es immer 'utf8', denke ich).

Ich habe ein Problem mit 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)) Scheint aber auf meiner Linux-Box zu funktionieren.

Die Vorgabe sollte auf jeden Fall utf-8 sein, aber nicht zwingend erzwungen.

mixmastamyk Ich hatte genau das gleiche Problem.
Meine App funktioniert einwandfrei, aber wenn ich das APK baue und auf meinem Android-Handy ausführe, erhalte ich:
UnicodeDecodeError: 'ascii'-Codec kann Byte 0xc3 in Position 352 nicht decodieren: Ordinalzahl nicht im Bereich (128)
Dies liegt daran, dass ich ein paar "É" in meiner Datei habe. Schade, dass ich in Python3 programmiert habe, um diese lästigen Dinge zu vermeiden.

Rechts. Sieht so aus, als ob Builder.load_file() standardmäßig utf8 verwenden sollte und/oder einen Codierungsparameter haben sollte. In der Zwischenzeit habe ich das gemacht:

 with open(filename, encoding='utf8') as f:
     Builder.load_string(f.read())

Stellen Sie sicher, dass Sie das automatische Laden für die kv-Datei deaktivieren, oder der Fehler wird immer noch ausgegeben und es sieht so aus, als hätte dies nicht funktioniert. Das '\u2026'-Formular kann auch funktionieren, wenn es nur ein oder zwei Zeichen enthält.

Intelligente Idee. Danke!
Ich werde das versuchen.

Dieses Problem wurde automatisch als veraltet markiert, da es in letzter Zeit keine Aktivität hatte. Es wird geschlossen, wenn keine weitere Aktivität stattfindet. Vielen Dank für Ihre Beiträge.

Wie praktisch, Fehler ignorieren und sich selbst schließen lassen.

Tatsächlich haben wir alte Probleme ausgegraben, um sie zu sortieren, kein gültiges und umsetzbares Problem wird geschlossen. Allerdings hilft diese Einstellung nicht bei der Motivation, unsere Nachmittage dem Projekt zu widmen.

War nicht irritiert über den Mangel an Arbeit, sondern eher ein Bot, der ignorierte Probleme schließt. Dieser kann möglicherweise eine oder zwei Codezeilen benötigen, um einen Codierungsparameter zu load_file hinzuzufügen. Hätte es selbst gemacht, aber es gibt 70 ausstehende Pull-Requests.

Ein Projekt mit knappem Personal sollte diese Art von Bot nicht haben.

Ich würde Sie dennoch ermutigen, diese Pull-Anfrage zu stellen. Wenn es sich um eine saubere und einfache Lösung handelt, besteht eine gute Chance, dass es zusammengeführt wird.

Ich habe das gleiche Problem mit kivy 1.10, meine App läuft perfekt unter Linux mit Python3 (python3 main.py), aber wenn ich die Bereitstellung auf meinem Android-Handy debugge, stürzt die App ab: / sehr ärgerlich, wenn Sie etwas mit Qualität machen möchten

Dieses Problem besteht immer noch mit kivy 1.10.1 und Python 3.6.6 unter Windows 10. Die aktuelle Problemumgehung besteht darin, die .kv-Datei nicht automatisch zu laden. Benennen Sie es in etwas um, das standardmäßig nicht geladen wird, speichern Sie es mit UTF8-Codierung und gehen Sie wie in #5154 gezeigt vor

from kivy.lang import Builder
with open('MyApp.renamed.kv', encoding='utf8') as f: 
    Builder.load_string(f.read())

@carasuca- Lösung funktioniert bei mir nicht

kivy 1.10.1 Python 3.5.3 Windows 7
gleiches Verhalten unter Windows 10 und Python 3.6.5

Derselbe Code funktioniert perfekt unter OSX und Linux

BEARBEITEN: Das Problem liegt in der #:include kv-Sprachdirektive
Die @carasuca- Lösung funktioniert genau dann, wenn Sie eine einzelne kv-Datei haben und diese mit Builder.load_string(f.read()) laden. Wenn dieser kv #:include otherfile.kv verwendet, wird diese Datei mit dem falschen Zeichensatz geladen.
Lösung 1: Legen Sie Ihren gesamten kv-Code in eine einzige Datei
Lösung 2:

for kvfile in ['file1.kv', 'file2.kv']:
         with open(kvfile, encoding='utf8') as f:
             Builder.load_string(f.read())

Nun, ich hatte den gleichen Fehler mit Wörtern wie "Número" oder "veículo". Ich habe es mit folgendem Code versucht:

from kivy.lang import Builder
with open('myApp.kv', encoding='utf8') as f: 
    Builder.load_string(f.read())

Aber ich hatte ein Problem damit. Als ich die App ausführte, konnte ich sehen, dass sich zwei verschiedene Labels überlappten.
Die Lösung bestand darin, die kv-Datei in einem Unterverzeichnis zu speichern und dann mit open wie folgt aufzurufen:

with open('./kvfile/myApp.kv', encoding='utf-8') as f:
            Builder.load_string(f.read())

Das Problem wurde gelöst, da das automatische Laden die kv-Datei nicht im selben Verzeichnis wie main.py findet. Die Visualisierung wird also nicht dupliziert.

@piontk Hey, ich dachte, das wäre meine Rettung, aber wenn ich es versuche, heißt es, dass "Encoding" kein gültiger Parameter für "open" ist. Wieso den? (Entschuldigung, wenn dies eine dumme Frage ist, es ist meine erste App überhaupt)

Ok, ich weiß, dass dies nicht ideal ist, aber wenn keine dieser Optionen für Sie funktioniert, können Sie Ihren gewünschten String auf eine Variable in der Haupt-App-Klasse in Ihrer .py-Datei mit UTF-8-Codierung setzen und dann darauf zugreifen in Ihrer .kv-Datei.
#.py
class MainApp(App):
struser = ('Nome de usuário')

#.kv
Label:
text: app.struser

hat bei mir funktioniert

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen