Labo288

プログラミングのこと、GISのこと、パソコンのこと、趣味のこと

ioStreamの取扱について

はじめに

Pythonでファイルの入出力処理を行う場合を考えます。私の例だと、ファイルの形式を変換して保存する処理を実装しました。この場合、ファイルの書き出しについて入門サイトでは新規ファイルをローカルに書き出して、データを追記する手順が紹介されます。しかしながら、ファイルとして保存する手順を踏まないでメモリ上で変換を完結させたいケースがあります(私の例では、ウェブアプリとして変換ツールを作成したので、どこにもファイルを保存しないで処理したかった)。

ioStreamの導入

標準ライブラリのひとつです。Python2と3でimport対象が異なります。

  • Python2の場合
#StringIO
from StringIO import StringIO
#stringio = StringIO()

#BytesIO
import io
#bytesio = io.BytesIO()
  • Python3の場合
#StringIO,BytesIO共通
import io
#stringio = io.StringIO()
#bytesio = io.BytesIO()

ioStreamの使い方

ioStreamのイメージとしては、保存先がメモリ上になっているファイルです。したがって、処理の最中の一時的な保存に向いています。また、その特性上処理が終わると消えてしまいます(メモリ管理とかはよくわかんないです)。

  • 実装例
#メモリ上のファイルとして定義
f = StringIO()
	#以下の行でCSVファイルをメモリ上に書き出し
	#よくある解説では、書き出し先のパスを指定したりするが、今回はStringIO()を指定
	writer = csv.writer(f, quotechar='"', quoting=csv.QUOTE_ALL, lineterminator="\n")
	#以下なんやかんやCSVファイルにデータを追記
	names = []
	for field in in_db.header.fields:
		names.append(field.name)
	writer.writerow(names)
	for rec in in_db:
		writer.writerow(rec.fieldData)
	#StringIO()の中身(CSVファイル)を取得する場合、必ずgetvalue()
	return f.getvalue()

StringIO vs BytesIO

一応、データの内容が文字列の場合StringIOを用いる、とされています。また先程紹介したとおり、Python2とPython3でインポートするモジュールが異なります。そんなわけで、互換性を考えるならBytesIOを使っておけば、2でも3でも同様に書けますね(どちらもio.BytesIO()であるため)。文字列データをBytesIOに入れたければエンコードしてバイト列に変換してから突っ込めばよいです。

参考
stackoverflow.com


まとめ

データの入出力はよくある処理だと思いますが、その処理ごとにいちいちデータを保存していると色々と面倒くさいはずですので、ioStreamを活用してシンプルなアプリケーションをつくりましょう。