Estoy desarrollando una aplicación multiplataforma para Linux y Windows 7. Todos mis archivos se escribieron primero en Linux y se codificaron como utf-8
, pero cuando abro este mismo proyecto en Windows, el archivo kv
se lee usando la codificación cp1252
. No parece que le suceda lo mismo a mis archivos .py
tal vez porque estoy usando python3.
Como consecuencia, los caracteres Unicode escritos en el archivo kv
no se mostrarán correctamente en la aplicación Kivy. La cadena 'Título'
se mostrará como TÃ-tulo
.
Mi configuración es: Kivy = 1.9.1, Python = 3.4.4, Windows 7 x64 Home Premium.
También mi Python se instaló usando Anaconda, pero probablemente esto no esté relacionado.
Escriba un archivo kv
codificado con utf-8
:
# test.kv
<myButton@Button>:
text: 'Título'
En el intérprete de Python o el 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 solución multiplataforma que encontré fue la siguiente:
# test.kv
<myButton@Button>:
text: str(b'T\xc3\xadtulo'.decode())
Para su información, una forma un poco más fácil de solucionar esto es usar literales Unicode:
<MyButton@Button>:
text: u'T\u00edtulo'
Gracias, lo usaré =)
Para otra persona que utilice esta solución alternativa, si desea encontrar la secuencia de escape Unicode para su carácter Unicode, puede encontrarla así:
>> hex( ord('ã') )
0xe3
>> u'\u00e3'
'ã'
¿No crees que debería haber una mejor manera? (escuchando a Hettinger hablar ...)
un encabezado # que diría cómo se debe manejar el carácter Unicode?
Incluso si este truco funciona ... hace que el texto sea realmente difícil de leer cuando hay muchos caracteres Unicode ...
¿Es esto solo un error de Windows?
Bueno, esta no es una forma recomendada de cómo manejar codificaciones, pero puede usar esto. Me funcionó en py2.7 con kivy 1.8.0, pero podría funcionar incluso con py3. Archivos guardados como utf-8
, \u...
símbolos usados directamente como u'ä'
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Sí @ChristianTremblay , esto es solo un error de Windows. En realidad, esto se debe a que la codificación predeterminada de Windows es cp1252, lo que hace que Kivy lea el archivo .kv como si estuviera codificado de esa manera. Tal vez la solución propuesta por @KeyWeeUsr realmente ayude, no lo he probado, pero podría ser más limpia que la otra solución alternativa propuesta.
Estoy de acuerdo, una buena solución sería permitir la especificación de codificación en el archivo .kv como podemos hacer en Python:
# -*- coding: utf-8 -*-
<MyWidget>:
# ...
¿Y si utf-8 fuera obligatorio para los archivos 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)
Esto se encuentra en kivy / lang / builder.py línea 275 y posteriores
@ChristianTremblay , creo que esto no sería lo mejor. Algunos usuarios aún pueden usar editores de texto con codificaciones predeterminadas diferentes de 'utf-8', por ejemplo, la codificación predeterminada de Windows 'cp1252'. Debemos brindar una solución para ambos.
Lo mejor probablemente sería imitar el comportamiento de Python:
Tener un problema en 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)) Sin embargo, parece funcionar en mi caja de Linux.
El valor predeterminado definitivamente debería ser utf-8, aunque no forzado como obligatorio.
mixmastamyk tuve exactamente el mismo problema.
Mi aplicación funciona bien, pero cuando construyo el APK y lo ejecuto en mi teléfono Android, obtengo:
UnicodeDecodeError: el códec 'ascii' no puede decodificar el byte 0xc3 en la posición 352: ordinal no está en el rango (128)
Esto se debe a que tengo un par de "É" en mi archivo. Lástima que estaba codificando en python3 para evitar este tipo de cosas molestas.
Derecha. Parece que Builder.load_file()
debería ser utf8 por defecto y / o tener un parámetro de codificación. Mientras tanto, hice esto:
with open(filename, encoding='utf8') as f:
Builder.load_string(f.read())
Asegúrese de deshabilitar la carga automática para el archivo kv, o el error seguirá apareciendo y parecerá que esto no funcionó. El formulario '\ u2026' también puede funcionar si es solo uno o dos caracteres.
Idea inteligente ¡Gracias!
Intentaré esto.
Este problema se ha marcado automáticamente como obsoleto porque no ha tenido actividad reciente. Se cerrará si no se produce más actividad. Gracias por sus aportaciones.
Qué conveniente, ignorar los errores y dejar que se cierren solos.
En realidad, hemos estado investigando problemas antiguos para clasificarlos, no se cerrará ningún problema válido y procesable. Aunque este tipo de actitud no ayuda con la motivación necesaria para dedicar nuestras tardes al proyecto.
No estaba irritado por la falta de trabajo, sino más bien por un bot que cierra los problemas ignorados. Este posiblemente necesite una o dos líneas de código para agregar un parámetro de codificación a load_file. Lo habría hecho yo mismo, pero hay 70 solicitudes de extracción pendientes.
Un proyecto con escasa mano de obra no debería tener este tipo de bot.
Aún así, te animo a que hagas esa solicitud de extracción. Si se trata de una solución limpia y sencilla, es muy probable que se fusione.
Tengo el mismo problema con kivy 1.10, mi aplicación funciona perfectamente en linux con python3 (python3 main.py) pero cuando depuro la implementación en mi teléfono Android, la aplicación se bloquea: / muy molesto si quieres hacer algo con calidad
Aún tengo este problema con kivy 1.10.1 y python 3.6.6 en Windows 10. La solución actual es no cargar automáticamente el archivo .kv. Cambie el nombre a algo que no se cargue por defecto, guárdelo con codificación utf8 y haga lo que se muestra en # 5154
from kivy.lang import Builder
with open('MyApp.renamed.kv', encoding='utf8') as f:
Builder.load_string(f.read())
La solución de
kivy 1.10.1 python 3.5.3 windows 7
mismo comportamiento en Windows 10 y Python 3.6.5
El mismo código funciona perfectamente en osx y linux
EDITAR: el problema está en la directiva de idioma #:include
kv
La solución
Solución 1: ponga todo su código kv en un solo archivo
Solución 2:
for kvfile in ['file1.kv', 'file2.kv']:
with open(kvfile, encoding='utf8') as f:
Builder.load_string(f.read())
Bueno, tuve el mismo error con palabras como "Número" o "veículo". Intenté con el siguiente código:
from kivy.lang import Builder
with open('myApp.kv', encoding='utf8') as f:
Builder.load_string(f.read())
Pero tuve un problema al hacer esto. Cuando ejecuté la aplicación, pude ver dos etiquetas diferentes superpuestas.
La solución fue guardar el archivo kv en un subdirectorio y luego llamar al with open así:
with open('./kvfile/myApp.kv', encoding='utf-8') as f:
Builder.load_string(f.read())
El problema se resolvió porque la carga automática no encuentra el archivo kv en el mismo directorio que main.py. Entonces no duplicará la visualización.
@piontk Oye, pensé que esta sería mi salvación, pero cuando lo intento, dice que 'codificación' no es un parámetro válido para 'abrir'. ¿Por qué? (Además, lo siento si esta es una pregunta tonta, es mi primera aplicación)
Ok, sé que esto no es ideal, pero si ninguna de estas opciones funciona para usted, puede configurar la cadena deseada en una variable en la clase de aplicación principal en su archivo .py, que tiene codificación utf-8, y luego acceder a ella en su archivo .kv.
#.py
class MainApp(App):
struser = ('Nome de usuário')
#.kv
Label:
text: app.struser
trabajó para mi
Comentario más útil
Sí @ChristianTremblay , esto es solo un error de Windows. En realidad, esto se debe a que la codificación predeterminada de Windows es cp1252, lo que hace que Kivy lea el archivo .kv como si estuviera codificado de esa manera. Tal vez la solución propuesta por @KeyWeeUsr realmente ayude, no lo he probado, pero podría ser más limpia que la otra solución alternativa propuesta.
Estoy de acuerdo, una buena solución sería permitir la especificación de codificación en el archivo .kv como podemos hacer en Python: