Python講座 / withと文字コードを指定してテキストファイルを読み書きする
テキストファイルは文字コードを明示し、with文で処理後に閉じるようにします。wモードは既存内容を切り詰めるため、新しい出力を作る操作と、保存済みデータを置き換える操作を区別します。
モードと文字コードを選ぶ
| モード | 目的 | 既存ファイルとの関係 |
|---|---|---|
| r | 読み取り | 存在しなければ失敗する |
| w | 内容を置き換える書き込み | 既存内容を切り詰める |
| a | 追記 | なければ作成する |
| x | 新規作成のみ | 存在すれば失敗する |
文字コードはバイト列とテキストを対応付ける規則です。UTF-8のデータにはencoding="utf-8"を指定し、環境の既定値へ依存しないようにします。errors="ignore"は読み取れない内容を捨てることがあるため、文字化けを隠す一般的な解決策にはしません。
パスとファイルエラーの回復は、try・except・else・finally・raiseで例外を扱うで扱う規則とつながります。
書き込み・追記・読み取りを実行する
不要になってよい専用フォルダーでtext_files.pyを保存し、仮想環境でpython text_files.pyを実行します。実行のたびにnotes-demo.txtをwモードで初期化する例です。
from pathlib import Path
path = Path("notes-demo.txt")
with path.open("w", encoding="utf-8", newline="\n") as f:
f.write("coffee:3500\n")
f.write("lunch:8000\n")
with path.open("a", encoding="utf-8") as f:
f.write("bus:2500\n")
with path.open("r", encoding="utf-8") as f:
for line in f:
print(line.rstrip("\n"))
予想結果です。
coffee:3500 lunch:8000 bus:2500
全体読み取りと行単位の処理を選ぶ
read()は残りの内容を文字列として返します。for line in fなら一行ずつ処理でき、必要がなければファイル全体をメモリーへ読み込まずに済みます。末尾まで読んだ後に再度読みたい場合は、開き直すか、意図して位置を移動します。
strip()は前後の空白も取り除くため、意味のある空白を失うことがあります。改行だけならrstrip("\n")のように対象を限定します。ファイルを開く際の改行設定によっても、改行文字が変換される場合があります。
原本を守り、ファイルの失敗を調べる
重要なデータは、別の一時ファイルへ書いて検証した後に、条件が整った場合だけ置き換える方法を検討します。withはファイルを閉じますが、書き込み前に切り詰めた元の内容を復元する機能ではありません。
FileNotFoundErrorではパスと親フォルダー、PermissionErrorでは権限やほかのアプリによるロックを調べます。UnicodeDecodeErrorでは実際の文字コードを特定し、バイトを捨てて済ませません。最初のwをaへ替えて二回目の重複を観察したら元へ戻します。pathlibで対象ファイルを特定してから、内容や文字コードを調べると切り分けやすくなります。
FileNotFoundErrorでは実際のパスと作業場所、UnicodeDecodeErrorでは実際の文字コード、PermissionErrorでは権限・ロック・ディレクトリーかどうかを確認します。すべての失敗を空文字列に変えると、ファイルがない場合と空の内容を区別できません。回復方針がある例外だけを処理します。




