web-dev-qa-db-ja.com

csvモジュールでio.StringIO()を使用するにはどうすればよいですか?

Python 3プログラムを2.7にバックポートしようとしましたが、奇妙な問題に悩まされています。

_>>> import io
>>> import csv
>>> output = io.StringIO()
>>> output.write("Hello!")            # Fail: io.StringIO expects Unicode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unicode argument expected, got 'str'
>>> output.write(u"Hello!")           # This works as expected.
6L
>>> writer = csv.writer(output)       # Now let's try this with the csv module:
>>> csvdata = [u"Hello", u"Goodbye"]  # Look ma, all Unicode! (?)
>>> writer.writerow(csvdata)          # Sadly, no.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unicode argument expected, got 'str'
_

ドキュメントによると、 io.StringIO() はUnicodeテキストのメモリ内ストリームを返します。 Unicode文字列を手動で入力しようとすると、正常に機能します。書き込まれているすべての文字列がUnicode文字列であっても、csvモジュールと一緒に失敗するのはなぜですか?例外を引き起こすstrはどこから来たのですか?

(私は代わりにStringIO.StringIO()を使用できることを知っていますが、このシナリオでio.StringIO()の何が問題になっているのでしょうか)

47
Tim Pietzcker

Python 2.7 csvモジュールはUnicode入力をサポートしていません: ドキュメントの冒頭の注 を参照してください。

Unicode文字列をバイト文字列にエンコードし、io.BytesIOの代わりにio.StringIOを使用する必要があるようです。

ドキュメントの examples セクションには、UnicodeReaderおよびUnicodeWriterラッパークラスの例が含まれています(ポインターについて@AlexeyKachayevに感謝します)。

49
Pedro Romano

StringIO.StringIO()を使用してください。

http://docs.python.org/library/io.html#io.StringIO

http://docs.python.org/library/stringio.html

io.StringIOはクラスです。 Unicodeを処理します。優先されるPython 3ライブラリ構造。

StringIO.StringIOはクラスです。文字列を処理します。従来のPython 2ライブラリ構造。

23
ernest

ファイルシステム上にCSVファイルを作成せずにFlask=を介してCSVファイルを直接提供しようとしたときに、これを見つけました。これは機能します。

import io
import csv

data = [[u'cell one', u'cell two'], [u'cell three', u'cell four']]

output = io.BytesIO()
writer = csv.writer(output, delimiter=',')
writer.writerows(data)
your_csv_string = output.getvalue()

こちらもご覧ください

7
Martin Thoma

csvドキュメントから:

Csvモジュールは、Unicodeの読み書きを直接サポートしていませんが、ASCII NUL文字に関する問題を8ビットクリーンで保存します。したがって、エンコードを処理する関数またはクラスを作成できますNULを使用するUTF-16のようなエンコードを避ける限り、デコードしますUTF-8をお勧めします。

UnicodeReaderUnicodeWriterの例はここにあります http://docs.python.org/2/library/csv.html

4
Alexey Kachayev

python 2.7の「メモリファイル」でCSVリーダー/ライターを使用するには:

from io import BytesIO
import csv

csv_data = """a,b,c
foo,bar,foo"""

# creates and stores your csv data into a file the csv reader can read (bytes)
memory_file_in = BytesIO(csv_data.encode(encoding='utf-8'))

# classic reader
reader = csv.DictReader(memory_file_in)

# writes a csv file
fieldnames = reader.fieldnames  # here we use the data from the above csv file
memory_file_out = BytesIO()     # create a memory file (bytes)

# classic writer (here we copy the first file in the second file)
writer = csv.DictWriter(memory_file_out, fieldnames)
for row in reader:
    print(row)
    writer.writerow(row)
0
pangur