2016-06-22 20 views
8

私は、csvファイルオブジェクトに文字列を書き込むためのpython 2/3互換コードを書き込もうとしています。このコード:csvのio.BytesIOへの書き込みは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) 

はのpython3でこのエラーを与える:

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

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

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

+0

@tdelaney私は、StringIOとBytesIOが(おそらく 'utf-8'の)ソーステキストに対して同じ表現を与えるかどうかはわかりませんでした。なぜ、私は同じ出力オブジェクトタイプを使用しようとしているのですか? – goelakash

答えて

8

Python3でcsv.writerは、ファイルモードのオブジェクトをテキストモードで開くことが必要です。 Python2では、csv.writerはファイル形式のオブジェクトがバイナリモードで開かれることを想定しています。 Python2にio.BytesIO使用しながら

したがって、のpython3に、io.StringIOを使用:のpython3でプリント上のコードを

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)) 

をPython2で

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

印刷物上のコード

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

これは良い解決策ですが、str *が*バイト形式のときにエラーが 'bytes'を要求する理由は何ですか? – goelakash

+0

私は、BytesIOオブジェクトからエラーが発生していると信じています。 'bytes'を予期したときに' str'が渡されたと不平を言っています。 Python3では 'str'は"バイトフォーマット "ではありません。ユニコード 'str'はコードポイントのシーケンスです。 – unutbu

+0

しかし、私はstr.encode()オブジェクト、事実上バイトオブジェクトを渡しました。それでは、どこに問題がありますか?このエラーは 'str'が渡されたことを示しています(単にPython 3について話しています)。 – goelakash

関連する問題