Python, Codificación de salida a UTF-8

Tengo una definición que construye una cadena compuesta de caracteres codificados en UTF-8. Los archivos de salida se abren con 'w+', "utf-8" argumentos 'w+', "utf-8" .

Sin embargo, cuando trato de x.write(string) obtengo el UnicodeEncodeError: 'ascii' codec can't encode character u'\ufeff' in position 1: ordinal not in range(128)

Supongo que esto se debe a que normalmente, por ejemplo, harías `print (u’something ‘). Pero necesito usar una variable y las citas en u ‘ _ ‘ niegan que …

¿Alguna sugerencia?

EDITAR: Código actual aquí:

 source = codecs.open("actionbreak/" + target + '.csv','r', "utf-8") outTarget = codecs.open("actionbreak/" + newTarget, 'w+', "utf-8") x = str(actionT(splitList[0], splitList[1])) outTarget.write(x) 

Esencialmente, todo lo que se supone que está haciendo es construirme una gran cantidad de cadenas que se parecen a esto:

[日木曜 Deliverables]= CASE WHEN things = 11 THEN C ELSE 0 END

¿Estás utilizando codecs.open() ? El open() incorporado de Python 2.7 no admite una encoding específica, lo que significa que tiene que codificar manualmente cadenas no ascii (como han dicho otros), pero codecs.open() admite eso y probablemente sea más fácil de eliminar en que la encoding manual de todas las cadenas.


Como en realidad estás usando codecs.open() , yendo por tu código agregado, y después de un poco de búsqueda, sugiero que intentes abrir el archivo de entrada y / o salida con la encoding "utf-8-sig" , que manejará automáticamente la lista de materiales para UTF-8 (consulte http://docs.python.org/2/library/codecs.html#encodings-and-unicode , cerca de la parte inferior de la sección) Pensaría que eso solo importaría el archivo de entrada, pero si ninguna de esas combinaciones (utf-8-sig / utf-8, utf-8 / utf-8-sig, utf-8-sig / utf-8-sig) funciona, entonces creo que la mayoría La situación probable sería que su archivo de entrada esté codificado en un formato Unicode diferente con la lista de materiales, ya que el códec UTF-8 predeterminado de Python interpreta las listas de materiales como caracteres regulares, por lo que la entrada no tendría ningún problema, pero la salida podría.


Solo noté esto, pero … cuando usas codecs.open() , espera una cadena Unicode, no una codificada; intente x = unicode(actionT(splitList[0], splitList[1])) .

Tu error también puede ocurrir cuando intentas decodificar una cadena Unicode (consulta http://wiki.python.org/moin/UnicodeEncodeError ), pero no creo que eso suceda a menos que actionT() o tu división de listas haga algo. a las cadenas de caracteres Unicode que hacen que se traten como cadenas que no son Unicode.

En Python 2.x hay dos tipos de cadena: cadena de bytes y cadena de Unicode. El primero contiene bytes y el último, puntos de código Unicode. Es fácil determinar qué tipo de cadena es: la cadena Unicode comienza con u :

 # byte string >>> 'abc' 'abc' # unicode string: >>> u'abc абв' u'abc \u0430\u0431\u0432' 

Los caracteres ‘abc’ son iguales, porque están en el rango ASCII. \u0430 es un punto de código Unicode, está fuera del rango ASCII. “Punto de código” es una representación interna de Python de puntos Unicode, no se pueden guardar en un archivo. Es necesario codificarlos a bytes primero. Aquí es cómo se ve la cadena de Unicode codificada (como se codifica, se convierte en una cadena de bytes):

 >>> s = u'abc абв' >>> s.encode('utf8') 'abc \xd0\xb0\xd0\xb1\xd0\xb2' 

Esta cadena codificada ahora se puede escribir en el archivo:

 >>> s = u'abc абв' >>> with open('text.txt', 'w+') as f: ... f.write(s.encode('utf8')) 

Ahora, es importante recordar qué encoding usamos al escribir en el archivo. Debido a que para poder leer los datos, necesitamos descifrar el contenido. Aquí cómo se ven los datos sin descodificar:

 >>> with open('text.txt', 'r') as f: ... content = f.read() >>> content 'abc \xd0\xb0\xd0\xb1\xd0\xb2' 

Verá, tenemos bytes codificados, exactamente igual que en s.encode (‘utf8’). Para decodificar es necesario proporcionar el nombre de encoding:

 >>> content.decode('utf8') u'abc \u0430\u0431\u0432' 

Después de la deencoding, hemos recuperado nuestra cadena Unicode con puntos de código Unicode.

 >>> print content.decode('utf8') abc абв 

xgord tiene razón, pero para futuras edificaciones vale la pena señalar exactamente lo que significa \ufeff . Se conoce como una byte order mark BOM o de byte order mark y, básicamente, es una callback a los primeros días de Unicode cuando las personas no podían ponerse de acuerdo sobre cómo querían que fuera su Unicode. Ahora todos los documentos Unicode están precedidos con un \ufeff o un \uffef según el orden en el que decidan organizar sus bytes.

Si encuentra un error en esos caracteres en la primera ubicación, puede estar seguro de que el problema es que no está intentando decodificarlo como utf-8, y es probable que el archivo aún esté bien.