2016-06-22 12 views
8

Próbuję napisać kod zgodny z Pythonem 2/3, aby napisać ciągi znaków do obiektu pliku csv. Ten kod:Zapisywanie do io.BytesIO w csv kończy się niepowodzeniem w python3

line_as_list = [line.encode() for line in line_as_list] 
writer_file = io.BytesIO() 
writer = csv.writer(writer_file, dialect=dialect, delimiter=self.delimiter) 
for line in line_as_list: 
    assert isinstance(line,bytes) 
    writer.writerow(line) 

daje ten błąd na Python3:

>   writer.writerow(line) 
E   TypeError: a bytes-like object is required, not 'str' 

Ale twierdzą, nie ma problemu z typem, więc dlaczego jest csv tworzenia błąd?

Nie mogę używać BytesIO tylko dla Pythona 2 i 3? Gdzie jest problem?

+0

@tdelaney Co miałem na myśli to nie jestem pewien, czy StringIO i BytesIO dadzą taką samą reprezentację dla tekstu źródłowego (prawdopodobnie w 'utf-8'). Właśnie dlatego próbuję użyć tego samego typu obiektu wyjściowego. – goelakash

Odpowiedz

8

W języku Python3 csv.writer oczekuje, że obiekt podobny do pliku zostanie otwarty w trybie tekstowym. W języku Python2, csv.writer oczekuje, że obiekt podobny do pliku zostanie otwarty w trybie binarnym.

Dlatego w Python3 użyć io.StringIO, natomiast w python2 użyciu io.BytesIO:

import io 
import csv 
import sys 
PY3 = sys.version_info[0] == 3 

line_as_list = [u'foo', u'bar'] 
encoding = 'utf-8' 

if PY3: 
    writer_file = io.StringIO() 
else: 
    writer_file = io.BytesIO() 
    line_as_list = [line.encode(encoding) for line in line_as_list] 

writer = csv.writer(writer_file, dialect='excel', delimiter=',') 
writer.writerow(line_as_list) 
content = writer_file.getvalue() 

if PY3: 
    content = content.encode(encoding) 

print(type(content)) 
print(repr(content)) 

W Python3 powyższy kod drukuje

<class 'bytes'> 
b'foo,bar\r\n' 

W python2 powyższy kod drukuje

<type 'str'> 
'foo,bar\r\n' 
+0

To dobre obejście, ale każdy pomysł, dlaczego błąd prosi o "bajty", gdy str * to * format bajtowy? – goelakash

+0

Wierzę, że błąd pochodzi z obiektu 'BytesIO' - narzeka, że ​​został przekazany' str' kiedy oczekiwano 'bytes'. W Python3 'str' nie jest" formatem bajtowym ". Unicode 'str' jest sekwencją punktów kodowych. – unutbu

+0

Ale przekazałem obiekt str.encode(), skutecznie obiekt bajtów. Więc gdzie jest problem? Ten błąd mówi, że 'str' został przekazany, gdy nie był (tylko rozmowa o Pythonie 3). – goelakash

Powiązane problemy