web-dev-qa-db-ja.com

Pythonでcsvのio.BytesIOへの書き込みが失敗する

私は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'

しかし、アサートはタイプに問題がないので、csvがエラーを作成するのはなぜですか?

Python 2と3の両方にのみBytesIOを使用できませんか?ここの問題はどこですか?

17
goelakash

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'
23
unutbu