Kivy: Windowsの「utf-8」kvファイルでのエンコードの問題

作成日 2016年02月16日  ·  24コメント  ·  ソース: kivy/kivy

LinuxとWindows7用のマルチプラットフォームアプリを開発しています。すべてのファイルは最初にLinuxで作成され、 utf-8としてエンコードされましたが、この同じプロジェクトをWindowsで開くと、 kvファイルが表示されます。 cp1252エンコーディングを使用して読み取られます。 python3を使用しているためか、 .pyファイルに同じことが起こらないようです。

結果として、 kvファイルに書き込まれたUnicode文字はKivyアプリで正しくレンダリングされません。 文字列'Título'TÃ-tuloとして表示されます。

私の設定は次のとおりです。Kivy= 1.9.1、Python = 3.4.4、Windows 7 x64HomePremium。

また、私のPythonはAnacondaを使用してインストールされましたが、これはおそらく無関係です。

問題を再現するには:

utf-8エンコードされたkvファイルを作成します。

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

Pythonインタープリターまたは.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によって提案された解決策が本当に役立つかもしれません、私はそれを試していませんが、提案された他の回避策よりもクリーンかもしれません。

私は同意します、良い解決策は、Pythonでできるように.kvファイルでエンコード指定を許可することです:

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

全てのコメント24件

参考までに-これを回避する少し簡単な方法は、Unicodeリテラルを使用することです。

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

ありがとう、私はそれを使用します=)

この回避策を使用している他の人にとって、Unicode文字のUnicodeエスケープシーケンスを見つけたい場合は、次のように見つけることができます。

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

もっと良い方法があるべきだと思いませんか? (ヘッティンガーが話すのを聞いて...)

ユニコード文字の処理方法を示す#ヘッダー?

このトリックが機能したとしても... Unicode文字がたくさんあるとテキストが本当に読みにくくなります...

これはWindowsのバグだけですか?

まあ、これはエンコーディングを処理するための推奨される方法ではありませんが、これを使用することができます。 py2.7ではkivy1.8.0で動作しましたが、py3でも動作する可能性があります。 utf-8として保存されたファイル、 \u...記号はu'ä'として直接使用されます

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

はい@ChristianTremblay 、これはWindowsのバグにすぎません。 これは実際には、Windowsのデフォルトのエンコードがcp1252であり、Kivyがそのようにエンコードされているかのように.kvファイルを読み取るためです。 @KeyWeeUsrによって提案された解決策が本当に役立つかもしれません、私はそれを試していませんが、提案された他の回避策よりもクリーンかもしれません。

私は同意します、良い解決策は、Pythonでできるように.kvファイルでエンコード指定を許可することです:

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

kvファイルにutf-8が必須だった場合はどうなりますか?

    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の275行目以降にあります

@ChristianTremblay 、これは最善ではないと思います。 一部のユーザーは、デフォルトのWindowsエンコーディング「cp1252」など、「utf-8」とは異なるデフォルトのエンコーディングでテキストエディタを使用する場合があります。 両方のソリューションを提供する必要があります。

おそらく、Pythonの動作を模倣するのが最善でしょう。

  • プログラマーが最初の行でエンコードを指定することを期待してください。
  • または、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スマートフォンで実行すると、次のようになります。
UnicodeDecodeError: 'ascii'コーデックは位置352のバイト0xc3をデコードできません:序数が範囲(128)にありません
これは、ファイルに「É」がいくつかあるためです。 残念ながら、このような迷惑なことを避けるためにpython3でコーディングしていました。

右。 Builder.load_file()はデフォルトでutf8に設定されているか、エンコードパラメータを持っている必要があるようです。 その間に私はこれをしました:

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

kvファイルの自動ロードを無効にしてください。無効にしないと、エラーがスローされ、これが機能しなかったように見えます。 '\ u2026'フォームは、1文字または2文字しかない場合にも機能します。

スマートなアイデア。ありがとう!
これを試してみます。

この問題は、最近のアクティビティがないため、自動的に古いものとしてマークされています。 それ以上のアクティビティが発生しない場合は閉じられます。 貢献していただきありがとうございます。

どれほど便利か、バグを無視して、バグを閉じさせてください。

実際、私たちは古い問題を切り分けてトリアージしてきました。有効で実行可能な問題はクローズされません。 この種の態度は、私たちの午後をプロジェクトに捧げるのに必要な動機付けには役立ちませんが。

仕事の不足にイライラしたのではなく、無視された問題を閉じるボットでした。 これは、load_fileにエンコーディングパラメータを追加するために1行または2行のコードを必要とする可能性があります。 自分でやったはずですが、70件の未処理のプルリクエストがあります。

マンパワーが不足しているプロジェクトには、このタイプのボットを含めるべきではありません。

それでも、プルリクエストを行うことをお勧めします。 クリーンで簡単な修正であれば、マージされる可能性が高くなります。

私はkivy1.10で同じ問題を抱えています、私のアプリはpython3(python3 main.py)を使用してLinuxで完全に実行されますが、Androidスマートフォンでデプロイをデバッグすると、アプリがクラッシュします:/品質で何かをしたい場合は非常に迷惑です

Windows10のkivy1.10.1およびpython3.6.6でもこの問題が発生します。現在の回避策は、.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
Windows10とPython3.6.5で同じ動作

同じコードがosxとlinuxで完全に機能します

編集:問題は#:include kv言語ディレクティブにあります
@carasucaソリューションは、単一のkvファイルがあり、Builder.load_string(f.read())を使用してロードした場合にのみ機能します。 そのkvが#:include anotherfile.kvを使用している場合、そのファイルには間違った文字セットがロードされます。
解決策1:すべてのkvコードを1つのファイルにまとめる
解決策2:解決策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())

しかし、私はこれを行うのに問題がありました。 アプリを実行すると、2つの異なるラベルが重なっているのがわかりました。
解決策は、kvファイルをサブディレクトリに保存してから、次のようにopenでを呼び出すことでした。

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

自動ロードでkvファイルがmain.pyと同じディレクトリに見つからないため、問題は解決しました。 したがって、視覚化が複製されることはありません。

@piontkねえ、これが私の救いだと思ったのですが、試してみると、「encoding」は「open」の有効なパラメータではないと表示されます。 どうして? (また、これがばかげた質問である場合は申し訳ありませんが、これは私の初めてのアプリです)

わかりました。これは理想的ではありませんが、これらのオプションのいずれも機能しない場合は、utf-8エンコードを含む.pyファイルのメインアプリクラスの変数に目的の文字列を設定して、それにアクセスできます。 .kvファイル内。
#.py
class MainApp(App):
struser = ('Nome de usuário')

#.kv
Label:
text: app.struser

私のために働いた

このページは役に立ちましたか?
0 / 5 - 0 評価