静かなる名辞

pythonとプログラミングのこと

【python】io.StringIOは便利なので使いこなそう

はじめに

 io.StringIOというものがあります。標準モジュールのioに属します。

16.2. io --- ストリームを扱うコアツール — Python 3.6.6 ドキュメント

 これがどう便利かというと、「ファイルオブジェクトのように見えるオブジェクト」を作れます。

読み込みに使ってみる

 こんな感じですかね。

import io

txt = """hoge
fuga
piyo
"""

f = io.StringIO(txt)
for line in f:
    print(line, end="")

""" =>
hoge
fuga
piyo
"""

 何が嬉しいかって? たとえば、これを見てください。

import io
import pandas as pd

txt = """
number,name,score
1,hoge,100
2,fuga,200
3,piyo,300
"""

df = pd.read_csv(io.StringIO(txt), index_col="number")
print(df)
""" =>
        name  score
number             
1       hoge    100
2       fuga    200
3       piyo    300
"""

 CSVの文字列を読み込むのに使っています。pandas.read_csvの第一引数はファイルパスかストリームしか受け付けませんが、io.StringIOをかましてやることでstrを渡せている訳です。

pandas.read_csv — pandas 0.23.1 documentation

 「ファイルを作るまでもない、作るのが面倒くさい」ような軽い確認やデバッグ作業に重宝します。

書き込んでみる

 io.StringIOが読み込みモードのファイルオブジェクトの代用品として使えることはわかりました。では、書き込みはどうでしょう?

import io
f = io.StringIO()
f.write("hoge\n")
f.close()

 このコードはエラーなく終了しますが、特に副作用は得られません。

 中身を見たければ、こうします。

import io
f = io.StringIO()
f.write("hoge\n")
print(f.getvalue())  # => hoge
f.close()

 StringIO.getvalue()はバッファに書き込まれた内容をすべて吐き出します。closeすると呼べなくなるので注意が必要です。

 こちらもpandasと組み合わせて使ってみます。

import io
import pandas as pd

txt = """
number,name,score
1,hoge,100
2,fuga,200
3,piyo,300
"""

df = pd.read_csv(io.StringIO(txt), index_col="number")

with io.StringIO() as f:
    f.write(df.to_csv())
    print(f.getvalue())

""" =>
number,name,score
1,hoge,100
2,fuga,200
3,piyo,300
"""

 使えているようです。

仲間たち

 ドキュメントを見るとbytes版のBytesIOもあることがわかる。他にも色々あるようだが、あまり目を通していないのでコメントしない。

16.2. io --- ストリームを扱うコアツール — Python 3.6.6 ドキュメント

まとめ

 テキストファイルを相手にするとき、データが小さければソースコードに埋め込めます。そうするとソースコードだけで再現性を確保できて、けっこう良いです。