はじめに
PythonのI/O操作は選択肢が多く、コーディング時、
どのクラスのメソッドを使うべきか、迷う場合あります。
自己メモ兼ねて、I/Oの全体像をまとめてみました。
I/Oのベースはファイルオブジェクト(ストリーム、file-likeオブジェクトと同義)
ファイルオブジェクトの定義をPython用語集から抜粋
- 下位リソースに対するファイル指向APIを提供
-
read()メソッド -
write()メソッド
-
- 下記リソースへのアクセス手段を提供
- ディスク上ファイル
- その他ストレージ
- 通信デバイス
- 標準入出力
- インメモリバッファ
- ソケット
- パイプ
ファイルオブジェクトの種類
- Text File
- テキストファイル
- Buffered Binary File
- バッファリング付きバイナリファイル
- Raw Binary File
- バッファリングなしバイナリファイル
ファイルオブジェクト操作のインターフェス
ioモジュールに定義されている
ioモジュールの定義をPythonドキュメントから抜粋
- ストリーム(=ファイルオブジェクト)を扱うコアツールで、様々な種類のI/Oを提供
- テキストストリームの
Text I/O-
strオブジェクトを受け取り(INPUT)、strオブジェクトを生成(OUTPUT) - データのエンコード・デコードを行う
- 改行文字変換を行う(オプショナル。プラットフォーム依存)
- テキストストリーム作成サンプル
f = open("myfile.txt", "r", encoding="utf-8")
-
- バイナリストリームの
Binary I/O(Buffered I/O)-
bytes-likeオブジェクトを受け取り(INPUT)、bytesオブジェクトを生成(OUTPUT) - データのエンコード、デコードを行わない
- 改行文字変換を行わない
- 非テキストデータだけでなく、テキストデータを自前処理したい場合も使用
- バイナリストリームの作成サンプル
f = open("myfile.jpg", "rb")
-
- Rawストリームの
Raw I/O(Unbuffered I/O)- バイナリストリームやテキストストリームの低レベル部品
- ユーザーコードで直接扱うべき場面は滅多にない
- Rawストリームの作成サンプル(バッファリングを無効にし、ファイルをバイナリーモードで開く)
f = open("myfile.jpg", "rb", buffering=0)
- バイナリストリームやテキストストリームの低レベル部品
- テキストストリームの
- ストリーム操作モード
- 読み込み専用
- 書き込み専用
- 読み書き
- ストリームアクセス方向
- ランダムアクセス
- 前方、後方の任意の場所にシーク
- シーケンシャルアクセス
- 一方向のみ(例えば、ソケットやパイプなど)
- ランダムアクセス
- ストリームのデータ型
- バイナリストリームは、
bytesオブジェクトのみサポート - テキストストリームは、
strオブジェクトのみサポート
- バイナリストリームは、
ストリームI/Oの検証
目的は、各種ストリームのINPUT、OUTPUTを確認。
テキストストリーム(Text I/O)
- テキストファイル
test_fileを作成
中身は漢字2文字(文字コードはUTF-8)
検証
- test_fileを読み込み専用、テキストモードで開く、
> python
>>> f = open("test_file", "r", encoding="utf-8")
openされたテキストストリームのタイプを確認すると、
TextIOWrapperクラスとなっています。
>>> type(f)
<class '_io.TextIOWrapper'>
ストリームを読み込むと、そのデータタイプは、
strクラスとなっています。
>>> data = f.read()
>>> type(data)
<class 'str'>
読み込まれたデータを出力すると、
漢字2文字検証が出力されます。
>>> print(data)
検証
バイナリストリーム(Binary I/O)
- test_fileを読み込み専用、バイナリモードで開く、
> python
>>> f = open("test_file", "rb")
openされたテキストストリームのタイプを確認すると、
BufferedReaderクラスとなっています。
>>> type(f)
<class '_io.BufferedReader'>
ストリームを読み込むと、そのデータタイプは、
bytesクラスとなっています。
>>> data = f.read()
>>> type(data)
<class 'bytes'>
読み込まれたデータを出力すると、
16進で6バイト出力されます。
>>> print(data)
b'\xe6\xa4\x9c\xe8\xa8\xbc'
漢字2文字検証のUTF-8コードを確認すると、
※ 参照: Unicode対応 文字コード表
検: E6A49C
証: E8A8BC
となり、上記バイト列と一致していることがわかりました。
Rawストリーム(Raw I/O)
- test_fileを読み込み専用、バッファリングを無効に、バイナリモードで開く、
> python
>>> f = open("test_file", "rb", buffering=0)
openされたテキストストリームのタイプを確認すると、
FileIOクラスとなっています。
>>> type(f)
<class '_io.FileIO'>
ストリームを読み込むと、そのデータタイプは、
bytesクラスとなっています。
>>> data = f.read()
>>> type(data)
<class 'bytes'>
読み込まれたデータを出力すると、
16進で6バイト出力されます。
>>> print(data)
b'\xe6\xa4\x9c\xe8\xa8\xbc'
漢字2文字検証のUTF-8コードと一致します。
バイナリストリームと同じ結果となりました。
おわりに
Pythonのストリーム種類とI/Oを検証してみました。
バッファリングあり・なしの違いが気になりますが、
次回のお楽しみとさせてください。
