Codificación Python – No se pudo decodificar a utf8

Tengo una base de datos sqlite que fue rellenada por un progtwig externo. Estoy tratando de leer los datos con python. Cuando bash leer los datos, aparece el siguiente error:

Error operacional: no se pudo decodificar a UTF-8

Si abro la base de datos en el administrador de sqlite y miro los datos de los registros ofensivos usando el buscador y búsqueda integrados, se ve bien, sin embargo, si exporto la tabla como CSV, observo que el carácter £ en los registros ofensivos se ha convertido  £

Si leo el csv en python, el £ en los registros ofensivos todavía se lee como  £ pero no es un problema, puedo analizarlo manualmente. Sin embargo, necesito poder leer los datos directamente desde la base de datos, sin el paso intermedio de convertir a csv.

He mirado algunas respuestas en línea para preguntas similares, hasta ahora he intentado configurar “text_factory = str” y también he intentado cambiar el tipo de datos de la columna de TEXT a BLOB usando el administrador de sqlite, pero aún así obtengo el error.

Mi código a continuación da como resultado el error operativo: no se pudo decodificar a UTF-8

conn = sqlite3.connect('test.db') conn.text_factory = str curr = conn.cursor() curr.execute('''SELECT xml_dump FROM hands_1 LIMIT 5000 , 5001''') row = curr.fetchone() 

Todos los registros superiores a 5000 en la base de datos tienen este problema de caracteres y, por lo tanto, producen el error.

Cualquier ayuda apreciada.

Python está tratando de ser útil al convertir fragmentos de texto (almacenados como bytes en una base de datos) en un objeto str python para usted. Para realizar esta conversión, Python debe adivinar qué letra representa cada byte (o grupo de bytes) que devuelve su consulta. La suposición predeterminada es una encoding llamada utf-8. Obviamente, esta suposición es incorrecta en su caso.

La solución es darle a Python una pequeña pista sobre cómo realizar la asignación de bytes a letras (es decir, caracteres Unicode). Ya te has acercado con la línea.

 conn.text_factory = str 

Sin embargo (según su respuesta en los comentarios anteriores), ya que está usando python 3, str es la fábrica de texto predeterminada , por lo que esa línea no hará nada nuevo por usted (consulte la documentación ).

Lo que sucede detrás de escena con esta línea es que Python intenta convertir los bytes devueltos por la consulta mediante la función str , algo así como:

 your_string = str(the_bytes, 'utf-8') # actually uses `conn.text_factory`, not `str` 

… pero quieres una encoding diferente donde está ‘utf-8’. Como no puede cambiar la encoding predeterminada de la función str , tendrá que imitarla de otra manera. Puede usar una función única sin nombre llamada lambda para esto:

 conn.text_factory = lambda x: str(x, 'latin1') 

Ahora, cuando la base de datos está entregando los bytes a python, python intentará asignarlos a letras usando el esquema ‘latin1’ en lugar del esquema ‘utf-8’. Por supuesto, no sé si latin1 es la encoding correcta de sus datos. Siendo realistas, tendrás que probar un puñado de codificaciones para encontrar la correcta. Yo probaría lo siguiente primero:

  • 'iso-8859-1'
  • 'utf-16'
  • 'utf-32'
  • 'latin1'

Puedes encontrar una lista más completa aquí .

Otra opción es simplemente dejar que los bytes que salen de la base de datos permanezcan como bytes. Si esta es una buena idea para usted depende de su aplicación. Puedes hacerlo configurando:

 conn.text_factory = bytes