Jak napisać UTF-8 w pliku CSV

84

Próbuję utworzyć plik tekstowy w formacie csv z PyQt4 QTableWidget. Chcę napisać tekst z kodowaniem UTF-8, ponieważ zawiera znaki specjalne. Używam następującego kodu:

import codecs
...
myfile = codecs.open(filename, 'w','utf-8')
...
f = result.table.item(i,c).text()
myfile.write(f+";")

Działa, dopóki komórka nie zawiera znaku specjalnego. Próbowałem też z

myfile = open(filename, 'w')
...
f = unicode(result.table.item(i,c).text(), "utf-8")

Ale zatrzymuje się również, gdy pojawia się znak specjalny. Nie mam pojęcia, co robię źle.

Jaskółka oknówka
źródło
"to również szczyty"? Co to znaczy? Jaki błąd otrzymujesz? Jaki jest twój wkład?
Dane wejściowe to pyqt4 QTableWidgetItem. Problem polega na tym, że nie dostaję żadnego błędu, ponieważ skrypt działa jako wtyczka.
Martin
Następnie spróbuj odtworzyć problem poza QT.
Znalazłem rozwiązanie. Musiałem napisaćmyfile.write(u"%s"&f+";")
Martin

Odpowiedzi:

106

Z twojego biegu powłoki:

pip2 install unicodecsv

I (w przeciwieństwie do pierwotnego pytania) zakładając, że używasz wbudowanego csvmodułu Pythona , zamień
import csvgo
import unicodecsv as csvw swój kod.

kqw
źródło
29
To nie zadziałało po prostu przez zastąpienie importu, musiałem również dodać kodowanie podczas tworzenia pisarza: writer = csv.writer(out, dialect='excel', encoding='utf-8')i utworzyć procedurę obsługi pliku za pomocą open(..., nie codecs.open(... .
Suzana
4
Wypróbowałem wszystkie sugestie na StackOverflow i tylko ta działa dla mnie.
Charles Chow,
95

To bardzo proste w przypadku Pythona 3.x ( dokumentacja ).

import csv

with open('output_file_name', 'w', newline='', encoding='utf-8') as csv_file:
    writer = csv.writer(csv_file, delimiter=';')
    writer.writerow('my_utf8_string')

W przypadku Pythona 2.x zajrzyj tutaj .

Zanon
źródło
1
co jeśli zawartość writerownie jest utf-8? czy to zadziała?
CKM
1
Nie ma potrzeby instalowania pip przez inne firmy.
Vaibhav Vishal
4

Dla mnie UnicodeWriterklasa z dokumentacji modułu Python 2 CSV tak naprawdę nie działała, ponieważ psuje csv.writer.write_row()interfejs.

Na przykład:

csv_writer = csv.writer(csv_file)
row = ['The meaning', 42]
csv_writer.writerow(row)

działa, podczas gdy:

csv_writer = UnicodeWriter(csv_file)
row = ['The meaning', 42]
csv_writer.writerow(row)

rzuci AttributeError: 'int' object has no attribute 'encode'.

Ponieważ UnicodeWriteroczywiście oczekujemy, że wszystkie wartości kolumn będą ciągami, możemy sami przekonwertować wartości i po prostu użyć domyślnego modułu CSV:

def to_utf8(lst):
    return [unicode(elem).encode('utf-8') for elem in lst]

...
csv_writer.writerow(to_utf8(row))

Lub możemy nawet małpować csv_writer, aby dodać write_utf8_rowfunkcję - ćwiczenie pozostawia się czytelnikowi.

Bojan Bogdanovic
źródło
znacznie prostsze rozwiązanie dla py2.x dla tych z nas, którzy wciąż go używają.
khan
2

Przykłady w dokumentacji Pythona pokazują, jak pisać pliki CSV Unicode: http://docs.python.org/2/library/csv.html#examples

(nie można tutaj skopiować kodu, ponieważ jest chroniony prawem autorskim)

Aaron Digulla
źródło
1
Dzięki za link. To było pomocne. Z mojej wiedzy, nawet jeśli zamieściłeś link, nie możesz skopiować wkleić kodu tutaj? (+1 za posiadanie praw autorskich)
Mutant
1
@Mutant: Kod nie jest jak prace naukowe. Kod jest chroniony prawem autorskim. Chociaż jestem na 99,999% pewien, że właściciele Pythona nie będą pozywać SO za kopiowanie ich kodu, nie miałem ochoty czytać ich długiej licencji, aby dowiedzieć się, czy jest to dozwolone, czy nie. Poza tym dobrze jest od czasu do czasu przypominać ludziom, że „Widzę to na moim monitorze”! = „Mogę z nim zrobić, co chcę” :-)
Aaron Digulla
1
Dzięki za przypomnienie. Niestety, świat, w którym żyjemy, stał się tak (nieracjonalnie) szybki i nieostrożny, w którym informacje płyną szybciej, niż można sobie wyobrazić, że wymaga to przypomnienia raz na jakiś czas przy ograniczeniu, które ma znaczenie. Dzięki za to :)
Mutant
2
Link do dokumentów jest na wpół przydatny (przykłady są lepsze), ale argument „prawa autorskie” jest tu przesadzony i bezsensowny. Python jest jawnie open source ( v2 v3 ). Licencja jest jasna: „nieodpłatna, ogólnoświatowa licencja na powielanie, analizowanie, testowanie, wykonywanie i / lub publiczne wyświetlanie, przygotowywanie dzieł pochodnych, rozpowszechnianie… [itd., Itd.]” Nawet proste sformułowanie w u góry strony, napis „zgodny z GPL” powinien zapewniać komfort. Udostępniaj rzeczy open source. Nawet zmodyfikuj, jeśli chcesz. Nie bez powodu to open source.
alttag
@alttag Kopiowanie lub używanie kodu GPLd w projekcie oznacza, że ​​cały pozostały kod w tym samym projekcie jest teraz również objęty GPL. Ponieważ nie jestem prawnikiem zajmującym się prawami autorskimi, nie wiem, co to oznacza w odniesieniu do kodu opublikowanego na stronie internetowej.
Aaron Digulla
0

W przypadku python2 możesz użyć tego kodu, zanim csv_writer.writerows(rows)
ten kod NIE skonwertuje liczb całkowitych na łańcuchy utf-8

def encode_rows_to_utf8 (wiersze):
    encoded_rows = []
    dla rzędu w rzędach:
        encoded_row = []
        dla wartości w wierszu:
            if isinstance (wartość, basestring):
                wartość = unicode (wartość) .encode ("utf-8")
            encoded_row.append (wartość)
        encoded_rows.append (encoded_row)
    return encoded_rows
pymen
źródło
-1

Bardzo prostym hackem jest użycie importu json zamiast csv. Na przykład zamiast csv.writer wykonaj następujące czynności:

    fd = codecs.open(tempfilename, 'wb', 'utf-8')  
    for c in whatever :
        fd.write( json.dumps(c) [1:-1] )   # json dumps writes ["a",..]
        fd.write('\n')
    fd.close()

Zasadniczo, biorąc pod uwagę listę pól w prawidłowej kolejności, sformatowany łańcuch json jest identyczny z wierszem csv, z wyjątkiem [i] odpowiednio na początku i na końcu. Wydaje się, że json jest odporny na utf-8 w Pythonie 2. *

vpathak
źródło