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?
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'