Kivy: مشكلة الترميز في ملف 'utf-8' kv على Windows

تم إنشاؤها على ١٦ فبراير ٢٠١٦  ·  24تعليقات  ·  مصدر: kivy/kivy

أقوم بتطوير تطبيق متعدد الأنظمة الأساسية لنظامي التشغيل Linux و Windows 7. تمت كتابة جميع ملفاتي لأول مرة على Linux وتم ترميزها كـ utf-8 ، ولكن عندما أفتح هذا المشروع نفسه على Windows ، فإن الملف kv تتم قراءتها باستخدام تشفير cp1252 . لا يبدو أن نفس الشيء يحدث لملفاتي .py ربما لأنني أستخدم python3.

نتيجة لذلك ، لن يتم عرض أحرف Unicode المكتوبة على ملف kv بشكل صحيح في تطبيق Kivy. ستظهر السلسلة 'Título' كـ TÃ-tulo .

إعداداتي هي: Kivy = 1.9.1 ، Python = 3.4.4 ، Windows 7 x64 Home Premium.

كما تم تثبيت الثعبان الخاص بي باستخدام Anaconda ، ولكن هذا ربما لا علاقة له.

لإعادة إنتاج المشكلة:

اكتب ملف kv مشفرًا بـ utf-8 :

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

على مترجم بايثون أو البرنامج النصي .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

كان الحل متعدد المنصات الذي وجدته كما يلي:

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

التعليق الأكثر فائدة

نعم ChristianTremblay ، هذا مجرد خطأ في Windows. هذا في الواقع لأن ترميز Windows الافتراضي هو cp1252 ، مما يجعل Kivy يقرأ ملف .kv كما لو كان مشفرًا بهذه الطريقة. ربما يساعد الحل الذي اقترحه KeyWeeUsr حقًا ، لم أجرب ذلك ، لكن قد يكون أنظف من الحل البديل المقترح.

أوافق على أن الحل الجيد هو السماح بمواصفات التشفير في ملف .kv مثل الطريقة التي يمكننا القيام بها في بيثون:

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

ال 24 كومينتر

لمعلوماتك - طريقة أسهل قليلاً للتغلب على هذا هي استخدام حرفي Unicode:

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

شكرًا لك ، سأستخدم ذلك =)

بالنسبة لشخص آخر يستخدم هذا الحل ، إذا كنت تريد العثور على تسلسل هروب Unicode لحرف Unicode الخاص بك ، فقد تجده مثل هذا:

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

ألا تعتقد أنه يجب أن يكون هناك طريقة أفضل؟ (قرع هيتنجر يتحدث ...)

# رأس التي من شأنها أن تخبرنا كيف ينبغي التعامل مع رمز يونيكود؟

حتى لو نجحت هذه الحيلة ... فهي تجعل قراءة النص صعبة حقًا عندما يكون هناك الكثير من أحرف unicode ...

هل هذا مجرد خلل في windows؟

حسنًا ، هذه ليست طريقة موصى بها للتعامل مع الترميزات ، ولكن يمكنك استخدام هذا. لقد نجحت معي في py2.7 مع kivy 1.8.0 ، لكنها يمكن أن تعمل حتى مع py3. تم حفظ الملفات كرموز utf-8 ، \u... تُستخدم مباشرة كرموز u'ä'

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

نعم ChristianTremblay ، هذا مجرد خطأ في Windows. هذا في الواقع لأن ترميز Windows الافتراضي هو cp1252 ، مما يجعل Kivy يقرأ ملف .kv كما لو كان مشفرًا بهذه الطريقة. ربما يساعد الحل الذي اقترحه KeyWeeUsr حقًا ، لم أجرب ذلك ، لكن قد يكون أنظف من الحل البديل المقترح.

أوافق على أن الحل الجيد هو السماح بمواصفات التشفير في ملف .kv مثل الطريقة التي يمكننا القيام بها في بيثون:

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

ماذا لو كان utf-8 إلزاميًا لملفات 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)

يوجد هذا في kivy / lang / builder.py line 275 وما فوق

ChristianTremblay ، أعتقد أن هذا لن يكون للأفضل. قد يستمر بعض المستخدمين في استخدام برامج تحرير النصوص بترميزات افتراضية مختلفة عن "utf-8" ، على سبيل المثال ترميز Windows الافتراضي "cp1252". يجب أن نقدم حلاً لكليهما.

من المحتمل أن يكون الأفضل هو تقليد سلوك الثعبان:

  • توقع أن يقوم المبرمج بتحديد الترميز في السطر الأول.
  • أو استخدم تشفير Python الافتراضي (أعتقد أنه في python3 سيكون دائمًا "utf8").

تواجه مشكلة على 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)) يبدو أنه يعمل على صندوق Linux الخاص بي بالرغم من ذلك.

يجب بالتأكيد أن يكون الإعداد الافتراضي هو utf-8 ، على الرغم من عدم فرضه على أنه إلزامي.

mixmastamyk كان لدي نفس المشكلة بالضبط.
يعمل تطبيقي بشكل جيد ، ولكن عندما أقوم بإنشاء ملف APK وتشغيله على هاتفي الذي يعمل بنظام Android ، أحصل على:
خطأ UnicodeDecode: لا يمكن لبرنامج الترميز 'ascii' فك تشفير البايت 0xc3 في الموضع 352: الترتيب الترتيبي ليس في النطاق (128)
هذا لأن لديّ اثنين من "É" في ملفي. من المؤسف أنني كنت أقوم بالترميز في python3 لتجنب هذا النوع من الأشياء المزعجة.

حق. يبدو أن Builder.load_file() يجب أن يكون افتراضيًا إلى utf8 و / أو يحتوي على معلمة ترميز. في هذه الأثناء فعلت هذا:

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

تأكد من تعطيل التحميل التلقائي لملف kv ، أو سيستمر طرح الخطأ وجعله يبدو كما لو أن هذا لم ينجح. يمكن أيضًا أن يعمل النموذج "\ u2026" إذا كان مجرد حرف أو حرفين.

فكرة ذكية شكرا!
سأحاول هذا.

تم وضع علامة على هذه المشكلة تلقائيًا على أنها قديمة نظرًا لعدم وجود نشاط حديث لها. سيتم إغلاقه إذا لم يحدث أي نشاط آخر. شكرا لمساهماتكم.

كم هو ملائم ، تجاهل الأخطاء ودعهم يغلقون أنفسهم.

في الواقع ، لقد بحثنا في المشكلات القديمة لفرزها ، ولن يتم إغلاق أي مشكلة صالحة وقابلة للتنفيذ. على الرغم من أن هذا النوع من المواقف لا يساعد في الحافز اللازم لتكريس فترة بعد الظهر للمشروع.

لم يكن منزعجًا من قلة العمل بل من الروبوت الذي يغلق المشكلات المتجاهلة. قد يستغرق هذا سطرًا واحدًا أو سطرين من التعليمات البرمجية لإضافة معلمة تشفير لتحميل ملف. كنت سأفعل ذلك بنفسي ، ولكن هناك 70 طلب سحب معلق.

لا ينبغي أن يحتوي المشروع ذو القوى العاملة الشحيحة على هذا النوع من الروبوتات.

ما زلت أشجعك على تقديم طلب السحب هذا. إذا كان إصلاحًا نظيفًا وسهلًا ، فهناك فرصة جيدة للدمج.

لدي نفس المشكلة مع kivy 1.10 ، يعمل تطبيقي بشكل مثالي على نظام Linux مع python3 (python3 main.py) ولكن عندما أقوم بتصحيح النشر على هاتفي الذي يعمل بنظام Android ، يتعطل التطبيق: / مزعج جدًا إذا كنت تريد القيام بشيء بجودة عالية

لا تزال تواجه هذه المشكلة مع kivy 1.10.1 و python 3.6.6 على Windows 10. الحل الحالي ليس تحميل ملف .kv تلقائيًا. أعد تسميته إلى شيء لا يتم تحميله افتراضيًا ، واحفظه بترميز utf8 وافعل كما هو موضح في # 5154

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

carasuca الحل لا يعمل بالنسبة لي

برنامج kivy 1.10.1 python 3.5.3 windows 7
نفس السلوك على windows 10 و python 3.6.5

نفس الكود يعمل بشكل مثالي على نظام التشغيل OSX و Linux

تحرير: المشكلة في توجيه اللغة #:include kv
يعمل حل carasuca فقط إذا كان لديك ملف kv واحد وقمت بتحميله باستخدام Builder.load_string (f.read ()). إذا كان kv يستخدم #: include anotherfile.kv ، فسيتم تحميل هذا الملف بمجموعة أحرف خاطئة.
الحل 1: ضع كل كود kv في ملف واحد
الحل 2:

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

حسنًا ، كان لدي نفس الخطأ مع كلمات مثل "Número" أو "veículo". حاولت باستخدام الكود التالي:

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

لكن كان لدي مشكلة في القيام بذلك. عندما قمت بتشغيل التطبيق ، كان بإمكاني رؤية علامتين مختلفتين متداخلتين.
كان الحل هو حفظ ملف kv في دليل فرعي ثم استدعاء بـ open مثل هذا:

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

تم حل المشكلة لأن التحميل التلقائي لن يعثر على ملف kv في نفس الدليل مثل main.py. لذلك لن يكرر التصور.

piontk مرحبًا ، اعتقدت أن هذا سيكون خلاصي ، لكن عندما أحاول ذلك ، يقول إن "الترميز" ليس معلمة صالحة لـ "فتح". لماذا ا؟ (أيضًا ، آسف إذا كان هذا سؤالًا غبيًا ، فهو أول تطبيق لي على الإطلاق)

حسنًا ، أعلم أن هذا ليس مثاليًا ولكن إذا لم يكن أي من هذه الخيارات مناسبًا لك ، فيمكنك تعيين السلسلة التي تريدها إلى متغير في فئة التطبيق الرئيسية في ملف .py ، الذي يحتوي على تشفير utf-8 ، ثم الوصول إليه في ملف .kv الخاص بك.
#.py
class MainApp(App):
struser = ('Nome de usuário')

#.kv
Label:
text: app.struser

عملت من أجلي

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات