2016-07-10 8 views
-2

In Python 2.7 und Ubuntu 14.04 I in eine CSV-Datei zu schreiben versuchen:UnicodeEncodeError: 'ascii' Codec kann nicht Zeichenfehler codiert writerow mit und Karte

csv_w.writerow(map(lambda x: flatdata.get(x, ""), columns))

das gibt mir die berüchtigten

UnicodeEncodeError: 'ascii' codec can't encode character u'\u265b' in position 19: ordinal not in range(128)

Fehler.

Die übliche Beratung hier ist unicode(x).encode("utf-8") ich dies versucht haben, und auch .encode("utf-8") im get für beide Parameter nur zu verwenden:

csv_w.writerow(map(lambda x: flatdata.get(unicode(x).encode("utf-8"), unicode("").encode("utf-8")), columns)) 

aber ich immer noch die gleichen Fehler.

Jede Hilfe wird sehr geschätzt, um den Fehler loszuwerden. (Ich stelle mir vor, die unicode("").encode("utf-8") ist ungeschickt, aber ich bin immer noch ein Newb).

EDIT: Mein vollständige Programm ist:

#!/usr/bin/env python 
import json 
import csv 
import fileinput 
import sys 
import glob 
import os 
def flattenjson(b, delim): 
val = {} 
for i in b.keys(): 
    if isinstance(b[i], dict): 
     get = flattenjson(b[i], delim) 
     for j in get.keys(): 
      val[ i + delim + j ] = get[j] 
    else: 
     val[i] = b[i] 
return val 
def createcolumnheadings(cols): 
    #create column headings 
    print ('a', cols) 
    columns = cols.keys() 
    columns = list(set(columns)) 
    print('b', columns) 
    return columns 
doOnce=True 
out_file= open('Excel.csv', 'wb') 
csv_w = csv.writer(out_file, delimiter="\t" ) 
print sys.argv, os.getcwd() 
os.chdir(sys.argv[1]) 
for line in fileinput.input(glob.glob("*.txt")): 
    print('filename:', fileinput.filename(),'line #:',fileinput.filelineno(),'line:', line) 
    data = json.loads(line) 
    flatdata = flattenjson(data, "__") 
    if doOnce: 
     columns=createcolumnheadings(flatdata)  
     print('c', columns) 
     csv_w.writerow(columns)     
     doOnce=False 
    csv_w.writerow(map(lambda x: flatdata.get(unicode(x).encode("utf-8"), unicode("").encode("utf-8")), columns)) 

Abgefaßtes einzigen Tweet, der den Fehler wirft UnicodeEncodeError: 'ascii' codec can't encode character u'\u2022' in position 14: ordinal not in range(128): here verfügbar ist.

LÖSUNG wie von Alistair empfohlen Ich habe Unicodescv installiert. Die Schritte waren: die Zip-Download von here

installieren: sudo pip installieren /path/to/zipfile/python-unicodecsv-master.zip

import unicodecsv as csv 
csv_w = csv.writer(f, encoding='utf-8') 
csv_w.writerow(flatdata.get(x, u'') for x in columns) 
+2

Können Sie ein komplettes Beispiel zeigen, mit Beispieldaten, so dass ich das Problem auf meinem Rechner wiedergeben kann und helfen? – Will

+0

Danke !! Ich habe das Programm hinzugefügt. Die Beispieldaten sind rassistische Tweets! Diese sind 1. rassistisch und 2. haben identifizierende Informationen. Könnte ich ihnen eine E-Mail schicken? – schoon

+0

Ich habe einen einzigen redigierten Tweet auf dropcanvas, Link am Ende der Frage. Danke noch einmal!! – schoon

Antwort

1

Ohne Ihre Daten zu sehen, würde es scheinen, dass Ihre Daten enthält Unicode-Datentypen (siehe How to fix: "UnicodeDecodeError: 'ascii' codec can't decode byte" für einen kurzen explination von Unicode vs. str Typen)

Ihre Lösung encode es ist dann anfällig Fehler - jede str mit nicht-ascii in i codiert t wird einen Fehler auslösen, wenn Sie unicode() es (Siehe vorherigen Link für die Erklärung).

Sie sollten alle Ihre Daten in Unicode-Typen erhalten, bevor Sie in CSV schreiben. Da das CSV-Modul von Python 2.7 defekt ist, müssen Sie den Ersetzungsalgorithmus verwenden: .

Sie können auch Ihre map in eine separate Anweisung ausbrechen, um Verwechslungen zu vermeiden. Stellen Sie sicher, dass Sie den vollständigen StackTrace und Beispiele für Ihren Code bereitstellen.

+0

Danke. Was meinst du "Python 2.7 CSV-Modul ist kaputt"? Ich verwende die Karte nur, weil ich sie ausgeschnitten und eingefügt habe. Gibt es eine Chance auf Anleitung, wie man es erweitert? – schoon

+0

Es unterstützt keine Python 2.x Unicode-Zeichenfolgen, was bedeutet, dass Sie Ihre Daten manuell codieren müssen - die Drop-in-Ersetzung behandelt die Codierung für Sie, sodass Sie nur Unicodes-Zeichenfolgen verwenden können und sich nicht um die Codierung in der Mitte Ihres Codes sorgen müssen. –

1
csv_w.writerow(map(lambda x: flatdata.get(unicode(x).encode("utf-8"), unicode("").encode("utf-8")), columns)) 

Sie haben die Parameter zu flatdata.get() weitergegeben codiert, dh die dict-Taste. Aber die Unicode-Zeichen sind nicht im Schlüssel, sie sind in dem Wert. Sie sollten den Wert von get() zurück kodieren:

csv_w.writerow([flatdata.get(x, u'').encode('utf-8') for x in columns]) 
+0

Danke. Dies gibt mir den neuen Fehler _csv.Error: Sequenz erwartet '. Irgendeine Idee warum? – schoon

+0

Hinzugefügt '[]' zu Argument, versuchen Sie es (es würde scheinen 'csv.writer' unterstützt keine Iteratoren?) – bobince

+0

Danke. Jetzt bekomme ich AttributeError: 'list' Objekt hat kein Attribut 'encode'. – schoon