2016-06-22 64 views
8

Sto provando a scrivere codice python 2/3 compatibile per scrivere stringhe sull'oggetto file csv. Questo codice:Scrittura su io.BytesIO in csv non riesce in 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) 

dà questo errore su python3:

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

Ma affermare non ha alcun problema con il tipo, quindi perché è csv creazione di un errore?

Non è possibile utilizzare BytesIO solo per Python 2 e 3? Dov'è il problema qui?

+0

@tdelaney Ciò che intendevo era che non sono sicuro che StringIO e BytesIO forniscano la stessa rappresentazione per il testo di origine (probabilmente in 'utf-8'). Ecco perché sto cercando di utilizzare lo stesso tipo di oggetto di output. – goelakash

risposta

8

In Python3 csv.writer si aspetta un oggetto simile a un file aperto in modalità testo. In Python2, csv.writer si aspetta un oggetto simile a un file aperto in modalità binaria.

Pertanto, in python3, utilizzare io.StringIO, mentre in python2 utilizzare 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)) 

In python3 codice precedente stampe

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

In python2 codice precedente stampe

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

Questa è una buona soluzione, ma nessuna idea del perché l'errore richiede "byte", quando str * è * un formato byte? – goelakash

+0

Credo che l'errore provenga dall'oggetto 'BytesIO' - si lamenta che è stato passato un' str' quando si aspettava 'byte'. In Python3 un 'str' non è un" formato byte ". Un unicode 'str' è una sequenza di punti di codice. – unutbu

+0

Ma ho passato un oggetto str.encode(), in effetti un oggetto byte. Allora dov'è il problema? Questo errore dice che è stato passato 'str', quando non lo era (solo parlando di Python 3). – goelakash