csv.Error: iterator powinien zwracać łańcuchy, a nie bajty

158

Sample.csv zawiera następujące elementy:

NAME    Id   No  Dept
Tom     1    12   CS
Hendry  2    35   EC
Bahamas 3    21   IT
Frank   4    61   EE

A plik Pythona zawiera następujący kod:

import csv
ifile  = open('sample.csv', "rb")
read = csv.reader(ifile)
for row in read :
    print (row) 

Kiedy uruchamiam powyższy kod w Pythonie, otrzymuję następujący wyjątek:

Plik „csvformat.py”, wiersz 4, w wierszu w czytaniu: _csv.Error: iterator powinien zwracać ciągi znaków, a nie bajty (czy otworzyłeś plik w trybie tekstowym?)

Jak mogę to naprawić?

Pika, czarodziej wielorybów
źródło

Odpowiedzi:

214

Otwierasz plik w trybie tekstowym.

Dokładniej:

ifile  = open('sample.csv', "rt", encoding=<theencodingofthefile>)

Dobre przypuszczenia dotyczące kodowania to „ascii” i „utf8”. Możesz również pozostawić kodowanie wyłączone i użyje domyślnego kodowania systemu, które zwykle jest UTF8, ale może być czymś innym.

Lennart Regebro
źródło
4
Chcę tylko dodać do tego, że jeśli wystąpią błędy kodowania podczas próby odczytu / zapisu z / do pliku CSV, dodanie określonego kodowania może pomóc. Właśnie naprawiłem ten błąd w moim, dodając „encoding = 'utf-8'”.
covfefe
96

Właśnie rozwiązałem ten problem z moim kodem. Powodem, dla którego rzuca ten wyjątek, jest to, że masz argument rb. Zmień to na r.

Twój kod:

import csv
ifile  = open('sample.csv', "rb")
read = csv.reader(ifile)
for row in read :
    print (row) 

Nowy kod:

import csv
ifile  = open('sample.csv', "r")
read = csv.reader(ifile)
for row in read :
    print (row)
MMM
źródło
29

Twój problem to masz bw openflagi. Flaga rt(odczyt, tekst) jest domyślna, więc korzystając z menedżera kontekstu, po prostu zrób to:

with open('sample.csv') as ifile:
    read = csv.reader(ifile) 
    for row in read:
        print (row)  

Menedżer kontekstu oznacza, że ​​nie potrzebujesz ogólnej obsługi błędów (bez której możesz utknąć z otwartym plikiem, szczególnie w interprecie), ponieważ automatycznie zamknie plik w przypadku błędu lub przy wyjściu z kontekstu.

Powyższe jest takie samo jak:

with open('sample.csv', 'r') as ifile:
    ...

lub

with open('sample.csv', 'rt') as ifile:
    ...
Aaron Hall
źródło
withOświadczenie aka kierownika kontekstowym nie ma nic wspólnego z tym pytaniem, w ogóle!
RayLuo,
4
@RayLuo Przedstawiając obsługę plików, zamierzam również zademonstrować najlepsze praktyki z tym związane. Robię to dość konsekwentnie. Jeśli dopiero zaczynasz przygodę z Pythonem i utkniesz w interaktywnej sesji z plikiem, z którym nie możesz nic zrobić, doceniłbyś moją radę ...
Aaron Hall
24

W Pythonie3 csv.readeroczekuje, że przekazana iterowalność zwraca ciągi, a nie bajty. Oto jeszcze jedno rozwiązanie tego problemu, które wykorzystuje codecsmoduł:

import csv
import codecs
ifile  = open('sample.csv', "rb")
read = csv.reader(codecs.iterdecode(ifile, 'utf-8'))
for row in read :
    print (row) 
Grigorij Michalkin
źródło
3
Pamiętaj, że ta opcja nie jest najbezpieczniejsza. Jeśli możesz użyć TextIOWrapper, powinieneś. Opisy problemów : iterdecode zjada puste ciągi znaków iterdecode nie jest bezpieczny w przypadku znaków wielobajtowych Rozwiązanie: TextIOWrapper w strumieniu CSV
kavdev
1
Dzięki! napotkał ten problem w Pythonie3.
Kenny Aires
9

Wystąpił ten błąd podczas uruchamiania starego skryptu Pythona opracowanego w Pythonie 2.6.4

Podczas aktualizacji do 3.6.2 musiałem usunąć wszystkie parametry „rb” z otwartych wywołań, aby naprawić ten błąd odczytu csv.

Michael Fayad
źródło