[前回] Python I/Oの再考(1): ストリームの種類と比較検証
はじめに
前回は、Python I/Oの基本をおさらいしました。
今回は、ioモジュールの高レベルインターフェースです。
ioモジュールが提供する高レベルインターフェース
バッファと文字コードに関係するインターフェースを取り上げます。
そもそもI/Oになぜバッファ(メモリ領域)が必要か
- Rawストリーム(バッファリングなし)
- ストリームの読み書きで、1バイトずつ処理するため性能が落ちる
 
- バイナリストリーム(バッファリングあり)
- バッファにデータをためて、一度に処理
 
io.DEFAULT_BUFFER_SIZEインターフェース
※ 参照: https://docs.python.org/ja/3/library/io.html#io.DEFAULT_BUFFER_SIZE
- 
バッファリング付きI/Oクラスで利用されるバッファの、デフォルトサイズを表す 
- 
open()時のバッファサイズには、ファイルのblksize値が使用される(os.stat()で取得可)- AlmaLinuxで取得した結果、4KB
 
- AlmaLinuxで取得した結果、
>>> import os
>>> os.stat("ファイル名").st_blksize
4096
テキストストリームの操作で、文字コード(encoding)指定を忘れず
- 
テキストストリームのデフォルト文字コード - OSのロケールに依存
- Windowsで取得してみると、cp932
 >>> import locale >>> locale.getpreferredencoding(False) 'cp932'- AlmaLinuxで取得してみると、UTF-8
 >>> import locale >>> locale.getpreferredencoding(False) 'UTF-8'
- Windowsで取得してみると、
 
- OSのロケールに依存
- 
テキストファイルを開くときは、文字コードを明示的に指定する必要あり - 理由は、Windowsはロケールの文字コードがUTF-8でないため
- UTF-8でエンコードされたテキストファイルが文字化けする
 
- 文字コードの指定方法
- UTF-8を使用する場合、encoding="utf-8"を渡す
 
- UTF-8を使用する場合、
 
- 理由は、Windowsはロケールの文字コードがUTF-8でないため
- 
Python 3.10以降で、現在ロケールの文字コードを使用する方法 - 
encoding="locale"を渡す
 
- 
io.text_encoding(encoding, stacklevel=2, /)
※ 参照: https://docs.python.org/ja/3/library/io.html#io.text_encoding
- 
Python 3.10以降で使用可能な、文字コード指定をチェックしてくれるヘルパー関数 - 
open()またはTextIOWrapperで、encoding=Noneパラメーターを指定する場面で使用
 
- 
- 
関数の戻り値 - 
encodingがNoneでない場合- 
encodingを返す
 
- 
- 
encodingがNoneの場合- 
localeを返す
 
- 
 
- 
- 
デフォルト文字コードが使用される場合、 EncodingWarningを発行するように設定可能- 
EncodingWarningの発行条件- 
sys.flags.warn_default_encodingがtrueで、encodingがNoneの場合
 
- 
- 
stacklevelは、警告が発行される場所を指定- 下記例では、read_text()の呼び出し元に対し、EncodingWarningが発行される
 
- 下記例では、
 
- 
def read_text(path, encoding=None):
    encoding = io.text_encoding(encoding)  # stacklevel=2
    with open(path, encoding) as f:
        return f.read()
おわりに
ioモジュールの高レベルインターフェースを理解しました。
次回をお楽しみに。


