Kivy: Masalah penyandian pada file kv 'utf-8' di Windows

Dibuat pada 16 Feb 2016  ·  24Komentar  ·  Sumber: kivy/kivy

Saya sedang mengembangkan aplikasi multi-platform untuk Linux dan Windows 7. Semua file saya pertama kali ditulis di Linux dan dikodekan sebagai utf-8 , tetapi ketika saya membuka proyek yang sama ini di Windows file kv dibaca menggunakan pengkodean cp1252 . Hal yang sama sepertinya tidak terjadi pada file .py saya mungkin karena saya menggunakan python3.

Akibatnya, karakter Unicode yang tertulis di file kv tidak akan ditampilkan dengan benar di aplikasi Kivy. String 'Título' akan ditampilkan sebagai TÃ-tulo .

Pengaturan saya adalah: Kivy=1.9.1, Python=3.4.4, Windows 7 x64 Home Premium.

Juga python saya diinstal menggunakan Anaconda, tetapi ini mungkin tidak terkait.

Untuk mereproduksi masalah:

Tulis file kv dikodekan dengan utf-8 :

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

Pada juru bahasa python atau skrip .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

Solusi multi-platform yang saya temukan adalah ini:

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

Komentar yang paling membantu

Ya @ChristianTremblay , ini hanya bug Windows. Ini sebenarnya karena pengkodean default windows adalah cp1252, menyebabkan Kivy membaca file .kv seolah-olah dikodekan seperti itu. Mungkin solusi yang diusulkan oleh @KeyWeeUsr sangat membantu, saya belum mencobanya, tetapi mungkin lebih bersih daripada solusi lain yang diusulkan.

Saya setuju, solusi yang baik adalah dengan mengizinkan spesifikasi encode pada file .kv seperti yang dapat kita lakukan dengan python:

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

Semua 24 komentar

FYI - cara yang sedikit lebih mudah untuk mengatasi ini adalah dengan menggunakan literal Unicode:

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

Terima kasih, saya akan menggunakannya =)

Untuk orang lain yang menggunakan pekerjaan ini, jika Anda ingin menemukan urutan pelarian Unicode untuk karakter Unicode Anda, Anda mungkin menemukannya seperti ini:

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

Tidakkah menurut Anda seharusnya ada cara yang lebih baik? (mendengarkan Hettinger berbicara...)

sebuah # header yang akan memberitahu bagaimana karakter unicode harus ditangani ?

Bahkan jika trik ini berhasil... itu membuat teks sangat sulit dibaca ketika ada banyak karakter unicode...

Apakah ini hanya bug windows?

Yah, ini bukan cara yang disarankan untuk menangani penyandian, tetapi Anda dapat menggunakan ini. Ini bekerja untuk saya di py2.7 dengan kivy 1.8.0, tetapi bisa bekerja bahkan dengan py3. File disimpan sebagai simbol utf-8 , \u... digunakan langsung sebagai u'ä'

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

Ya @ChristianTremblay , ini hanya bug Windows. Ini sebenarnya karena pengkodean default windows adalah cp1252, menyebabkan Kivy membaca file .kv seolah-olah dikodekan seperti itu. Mungkin solusi yang diusulkan oleh @KeyWeeUsr sangat membantu, saya belum mencobanya, tetapi mungkin lebih bersih daripada solusi lain yang diusulkan.

Saya setuju, solusi yang baik adalah dengan mengizinkan spesifikasi encode pada file .kv seperti yang dapat kita lakukan dengan python:

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

Bagaimana jika utf-8 wajib untuk file 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)

Ini ditemukan di kivy/lang/builder.py baris 275 dan lebih tinggi

@ChristianTremblay , saya pikir ini bukan yang terbaik. Beberapa pengguna mungkin masih menggunakan editor teks dengan penyandian default yang berbeda dari 'utf-8', misalnya penyandian Windows bawaan 'cp1252'. Kita harus memberikan solusi untuk keduanya.

Yang terbaik mungkin adalah meniru perilaku python:

  • Harapkan programmer untuk menentukan pengkodean pada baris pertama.
  • Atau gunakan pengkodean default python (pada python3 itu akan selalu menjadi 'utf8' saya pikir).

Mengalami masalah di 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)) Tampaknya berfungsi di kotak Linux saya.

Defaultnya pasti utf-8, meskipun tidak dipaksakan sebagai wajib.

mixmastamyk saya memiliki masalah yang sama persis.
Aplikasi saya berfungsi dengan baik, tetapi ketika saya membuat APK dan menjalankannya di ponsel Android saya, saya mendapatkan:
UnicodeDecodeError: codec 'ascii' tidak dapat mendekode byte 0xc3 di posisi 352: ordinal tidak dalam jangkauan (128)
Ini karena saya memiliki beberapa "É" di file saya. Sayang sekali saya sedang coding di python3 untuk menghindari hal-hal yang mengganggu semacam ini.

Benar. Sepertinya Builder.load_file() harus default ke utf8 dan/atau memiliki parameter penyandian. Sementara itu saya melakukan ini:

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

Pastikan untuk menonaktifkan pemuatan otomatis untuk file kv, atau kesalahan akan tetap muncul dan membuatnya terlihat seperti ini tidak berhasil. Formulir '\u2026' juga dapat berfungsi jika hanya satu atau dua karakter.

Ide cerdas. terima kasih!
Saya akan mencoba ini.

Masalah ini secara otomatis ditandai sebagai basi karena tidak ada aktivitas terbaru. Ini akan ditutup jika tidak ada aktivitas lebih lanjut yang terjadi. Terima kasih atas kontribusi Anda.

Betapa nyamannya, abaikan bug dan biarkan mereka menutup sendiri.

Sebenarnya kami telah menggali masalah lama untuk melakukan triase, tidak ada masalah yang valid dan dapat ditindaklanjuti yang akan ditutup. Meskipun sikap seperti ini tidak membantu dengan motivasi yang dibutuhkan untuk mendedikasikan sore hari kami untuk proyek tersebut.

Tidak kesal karena kurangnya pekerjaan melainkan bot yang menutup masalah yang diabaikan. Yang ini mungkin membutuhkan satu atau dua baris kode untuk menambahkan parameter pengkodean ke load_file. Akan melakukannya sendiri, tetapi ada 70 permintaan tarik yang luar biasa.

Sebuah proyek dengan tenaga kerja yang langka seharusnya tidak memiliki bot jenis ini.

Saya masih mendorong Anda untuk membuat permintaan tarik itu. Jika itu adalah perbaikan yang bersih dan mudah, itu memiliki peluang bagus untuk digabungkan.

Saya memiliki masalah yang sama dengan kivy 1.10, aplikasi saya berjalan sempurna di linux dengan python3 ( python3 main.py) tetapi ketika saya men-debug penyebaran di ponsel Android saya, aplikasi macet:/ sangat mengganggu jika Anda ingin melakukan sesuatu dengan kualitas

Masih mengalami masalah ini dengan kivy 1.10.1 dan python 3.6.6 pada Windows 10. Solusi saat ini adalah tidak memuat file .kv secara otomatis. Ubah namanya menjadi sesuatu yang tidak dimuat secara default, simpan dengan pengkodean utf8 dan lakukan seperti yang ditunjukkan pada #5154

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

Solusi @carasuca tidak berfungsi untuk saya

kivy 1.10.1 python 3.5.3 windows 7
perilaku yang sama pada windows 10 dan python 3.6.5

Kode yang sama berfungsi dengan baik di osx dan linux

EDIT: masalahnya ada di arahan bahasa #:include kv
Solusi @carasuca berfungsi jika dan hanya jika Anda memiliki satu file kv dan Anda memuatnya menggunakan Builder.load_string(f.read()). Jika kv tersebut menggunakan #:include anotherfile.kv, file tersebut akan dimuat dengan rangkaian karakter yang salah.
Solusi 1: masukkan semua kode kv Anda ke dalam satu file
Solusi 2:

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

Yah saya memiliki kesalahan yang sama dengan kata-kata seperti "Número" atau "veículo". Saya mencoba dengan kode berikut:

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

Tapi saya punya masalah melakukan ini. Ketika saya menjalankan Aplikasi, saya dapat melihat dua label berbeda tumpang tindih.
Solusinya adalah menyimpan file kv di subdirektori dan kemudian memanggil dengan open seperti ini:

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

Masalahnya terpecahkan karena pemuatan otomatis tidak akan menemukan file kv ke dalam direktori yang sama dengan main.py. Jadi itu tidak akan menduplikasi visualisasi.

@piontk Hei, saya pikir ini akan menjadi keselamatan saya, tetapi ketika saya mencobanya, dikatakan 'encoding' bukan parameter yang valid untuk 'open'. Mengapa? (Juga, maaf jika ini adalah pertanyaan bodoh, ini adalah aplikasi pertama saya)

Oke, saya tahu ini tidak ideal tetapi jika tidak ada opsi ini yang berfungsi untuk Anda, Anda dapat mengatur string yang Anda inginkan ke variabel di kelas aplikasi utama di file .py Anda, yang memiliki penyandian utf-8, dan kemudian mengaksesnya di file .kv Anda.
#.py
class MainApp(App):
struser = ('Nome de usuário')

#.kv
Label:
text: app.struser

bekerja untuk saya

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

hansent picture hansent  ·  3Komentar

Fogapod picture Fogapod  ·  6Komentar

37 picture 37  ·  4Komentar

damienflament picture damienflament  ·  3Komentar

sbrother picture sbrother  ·  4Komentar