Запись в io.BytesIO в csv завершается неудачей в python3
Я пытаюсь написать Python 2/3 совместимый код для записи строк в объект файла CSV. Этот код:
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)
Выдает эту ошибку на Python3:
> writer.writerow(line)
E TypeError: a bytes-like object is required, not 'str'
Но у assert нет проблем с типом, так почему csv
создать ошибку?
Я не могу использовать BytesIO
только для Python 2 и 3? Где здесь проблема?
1 ответ
Решение
В Python3 csv.writer
ожидает файловый объект, открытый в текстовом режиме. В Python2 csv.writer
ожидает файловый объект, открытый в двоичном режиме.
Поэтому в Python3 используйте io.StringIO
, в то время как в Python2 использовать 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))
В Python3 код выше печатает
<class 'bytes'>
b'foo,bar\r\n'
В Python2 код выше печатает
<type 'str'>
'foo,bar\r\n'