Django crea un archivo CSV que contiene Unicode y se puede abrir directamente con Excel

Quiero crear un archivo CSV a través de Django que contiene datos Unicode (caracteres griegos) y quiero que se abra directamente desde MS Excel. En otros lugares había leído sobre la biblioteca de Unicodecsv y decidí usar eso. Entonces, aquí está mi punto de vista;

 def get_csv (solicitud, id):
     response = HttpResponse (mimetype = 'text / csv')
     respuesta ['Content-Disposition'] = 'archivo adjunto;  nombre_archivo = csv.csv '
     writer = unicodecsv.writer (respuesta, encoding = 'utf-16 "')
     writer.writerow (['Second row', 'A', 'B', 'C', '"Testing"', "ελληνικά"])
     respuesta de retorno

Ahora, excepto utf-16, realmente había intentado todo en el parámetro de encoding del escritor, incluidos utf-8, utf-8-sig, utf-8-le, utf-16-le y quizás otros. Cada vez que abría el archivo con Excel siempre veía basura donde deberían haber estado los caracteres griegos.

Notepad ++ pudo abrir el archivo sin problemas. Qué estoy haciendo mal ?

Actualización: esto es lo que intenté después de la respuesta de jd:

 importar csv
 response = HttpResponse (mimetype = 'text / csv')
 respuesta ['Content-Disposition'] = 'archivo adjunto;  nombre_archivo = prueba.csv '
 response.write (u '\ ufeff'.encode (' utf8 '))
 writer = csv.writer (respuesta, delimitador = ';', dialecto = 'excel')
 writer.writerow (['Second row', 'A', 'B', 'C', '"Testing"', "ελληνικά"])
 respuesta de retorno

Todavía no tengo suerte, ahora también puedo ver la lista de materiales (como acaparamiento) en Excel. También intenté usar unicodecsv y algunas otras opciones, pero una vez más nothign trabajó 🙁

Actualización 2: intenté esto después de la propuesta de dda:

 writer = unicodecsv.writer (respuesta, delimitador = ';', dialecto = 'excel')
 writer.writerow (codecs.BOM_UTF16_LE)
 writer.writerow ([(u'ελληνικά '). decode (' utf8 '). encode (' utf_16_le ')])

Aún no hay suerte 🙁 Aquí está el error que recibo:

 UnicodeEncodeError en / csv / 559
 El codec 'ascii' no puede codificar caracteres en la posición 0-7: ordinal no en rango (128)

Actualización 3: Me estoy volviendo loco. Por qué es tan dificil ??? Aquí hay otro bash:

 response.write (codecs.BOM_UTF16_LE)
 writer = unicodecsv.writer (respuesta, delimitador = ';', lineterminator = '\ n', dialect = 'excel',)
 writer.writerow ('ελληνικ')
 writer.writerow ([('ελληνικά'). decode ('utf8'). encode ('utf_16_le')]) #A
 writer.writerow ([('ελληνικά2'). decode ('utf8'). encode ('utf_16_le'), ('ελληνικά2'). decode ('utf8'). encode ('utf_16_le')]) #B

Y aquí está el contenido del Excel:

㮵 ε ε ελληνικά

Así que tengo algunos caracteres griegos con la línea #A. Pero la línea B, que es exactamente la misma, no me produjo los caracteres griegos $ ^ # $ # ^ $ # $ # ^ @@% $ # ^ # ^ $ # $ Pls hlep!

Con el módulo csv de Python, puede escribir un archivo UTF-8 que Excel leerá correctamente si coloca una lista de materiales al principio del archivo.

 with open('myfile.csv', 'wb') as f: f.write(u'\ufeff'.encode('utf8')) writer = csv.writer(f, delimiter=';', lineterminator='\n', quoting=csv.QUOTE_ALL, dialect='excel') ... 

Lo mismo debería funcionar con unicodecsv . Supongo que puede escribir la lista de materiales directamente en el objeto HttpResponse , si no puede usar StringIO para escribir primero su archivo.

Editar:

Aquí hay algunos ejemplos de código que escribe un archivo CSV UTF-8 con caracteres que no son ASCII. Estoy sacando a Django de la ecuación por simplicidad. Puedo leer ese archivo en Excel.

 # -*- coding: utf-8 -*- import csv import os response = open(os.path.expanduser('~/utf8_test.csv'), 'wb') response.write(u'\ufeff'.encode('utf8')) writer = csv.writer(response, delimiter=';' , dialect='excel') writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', u"ελληνικά".encode('utf8')]) response.close() 

Nunca he podido abrir un archivo codificado en UTF-8 (CSV) en Excel. La única forma en que logré hacer los archivos de importación de Excel correctamente fue con UTF-16LE. YMMV.

EDITAR

primero

 writer.writerow(codecs.BOM_UTF16_LE) 

Luego (tantas veces como sea necesario; str es la cadena para codificar y escribir)

 writer.writerow(str.decode('utf8').encode('utf_16_le'))