web-dev-qa-db-fra.com

L'écriture dans io.BytesIO en csv échoue en python3

J'essaie d'écrire python 2/3 de code compatible pour écrire des chaînes dans un objet fichier csv. Ce code:

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)

Donne cette erreur sur Python3:

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

Mais assert n'a aucun problème avec le type, alors pourquoi csv crée-t-il une erreur?

Puis-je utiliser BytesIO uniquement pour les deux Python 2 et 3? Où est le problème ici?

17
goelakash

En Python3 csv.writer attend un objet de type fichier ouvert en mode texte. En Python2, csv.writer attend un objet de type fichier ouvert en mode binaire.

Par conséquent, en Python3, utilisez io.StringIO, en Python2, utilisez 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))

En Python3, le code ci-dessus s'imprime

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

En Python2, le code ci-dessus s'imprime

<type 'str'>
'foo,bar\r\n'
23
unutbu