テキストファイルの読み込みは、Python学習の最初の関門です。
本記事では、全文読み込み、行単位の読み込み、文字コードや改行の扱い、エラー対応までを入門者向けにやさしく整理します。
まずは基本のopen()
から、実践的なwith
構文、そして大きいファイルへの対応を順に見ていきます。
Pythonでテキストファイルを読み込む基本
入門段階では、「どう開くか」と「いつ閉じるか」を正しく理解することが最重要です。
Pythonではopen()
でファイルを開き、文字列として内容を受け取ります。
特にwith文を使うと自動でクローズでき、ミスを防げます。
open()とread()で全文を読む(コード例)
まずは最小コードで全文を一度に読み込む方法です。
これは小さなファイル向けで、内容を一気に文字列で受け取ります。
サンプルファイル(sample.txt)の内容
このファイルが存在している前提で進めます。
内容は次のとおりです。
一行目: Pythonでテキストを読みます。
二行目: 改行や空白を含みます。
三行目: 終わり。
コード例: open() + read() を使う
# sample.txt を全文読み込んで表示する基本パターン
# 注意: 大きいファイルではメモリを多く消費します
# 1. ファイルを開く (デフォルトは読み込みモード'r')
f = open("sample.txt", "r", encoding="utf-8") # 文字化け防止のため encoding を明示
# 2. 全文を一度に読み込む
text = f.read() # 返り値は1つの長い文字列
# 3. 忘れずに閉じる
f.close()
# 4. 読み込んだ内容を表示
print(text)
一行目: Pythonでテキストを読みます。
二行目: 改行や空白を含みます。
三行目: 終わり。
read()は全内容を一気にメモリへ読み込むため、大きいファイルでは不向きです。
必ずf.close()
で閉じる必要があり、閉じ忘れ防止のために次のwith
構文が推奨されます。
with文で安全に読み込む
with構文は、処理が終わると自動でファイルを閉じてくれる安全な書き方です。
初心者はまずこれを標準形として覚えると良いです。
# with を使えばブロックを抜けた時点で自動的に close されます
# エンコーディングは原則 UTF-8 を明示します
with open("sample.txt", "r", encoding="utf-8") as f:
text = f.read()
print("全文の文字数:", len(text))
print("--- ファイル内容 ---")
print(text) # 必要に応じて print せず、文字列として扱ってもOK
全文の文字数: 53
--- ファイル内容 ---
一行目: Pythonでテキストを読みます。
二行目: 改行や空白を含みます。
三行目: 終わり。
with構文を使えば、例外が起きても確実にクローズされるため、基本は常にwith open(...)
を使うようにしましょう。
ファイルパスの指定(相対/絶対)
ファイルが見つからない多くの原因は「パスの解釈違い」です。
相対パスは「カレントディレクトリ」基準、絶対パスは「ルート」からの完全な道筋です。
安定したコードにはpathlibの利用が便利です。
表: 相対パスと絶対パスの違い
種別 | 記述例 | 解説 |
---|---|---|
相対パス | data/sample.txt | 実行時点のカレントディレクトリからの相対位置 |
絶対パス(Windows) | C:/project/data/sample.txt | 先頭にドライブを含む完全パス |
絶対パス(mac/Linux) | /Users/alice/project/data/sample.txt | ルート(/)からの完全パス |
from pathlib import Path
# カレントディレクトリの確認
print("CWD:", Path.cwd())
# 相対パス -> 絶対パスへ変換
rel = Path("sample.txt")
print("相対 -> 絶対:", rel.resolve())
# スクリプトファイルと同じ場所のファイルを参照したい場合
# (__file__ が使えない実行環境もあるため try/except を併用)
try:
here = Path(__file__).resolve().parent # スクリプトのある場所
path = here / "sample.txt"
print("スクリプト隣接パス:", path)
except NameError:
print("__file__ が未定義の環境(対話/Notebook)では Path.cwd() を基準にしてください。")
CWD: /Users/you/work
相対 -> 絶対: /Users/you/work/sample.txt
スクリプト隣接パス: /Users/you/work/sample.txt
Jupyterや対話実行では__file__が未定義の場合があるため、Path.cwd()基準で考えるのが安全です。
行ごとに読み込む
全文ではなく、行単位に処理したい場合は「イテレータとしてのファイルオブジェクト」を活用します。
これによりメモリ効率よく処理できます。
for文で1行ずつ読む(コード例)
最もPythonicで、かつ大きいファイルにも強いのがforループでの逐次読み込みです。
# ファイルを1行ずつ処理する例
# print 時に末尾の改行が重複しないよう rstrip("\n") を使用
with open("sample.txt", "r", encoding="utf-8") as f:
for i, line in enumerate(f, start=1):
line_no_newline = line.rstrip("\n") # 改行だけ除去
print(f"{i:02d}: {line_no_newline}")
01: 一行目: Pythonでテキストを読みます。
02: 二行目: 改行や空白を含みます。
03: 三行目: 終わり。
rstrip(“\n”)は改行だけを安全に取り除けるため、末尾のスペースを保持したいときに有効です。
readline()で次の1行だけ読む
readline()は「ポインタ位置から1行だけ」取り出す関数で、対話的処理やヘッダ行のスキップなどに向きます。
# readline() は呼ぶたびに次の1行を返す
with open("sample.txt", "r", encoding="utf-8") as f:
first = f.readline()
second = f.readline()
print("1行目:", first.rstrip("\n"))
print("2行目:", second.rstrip("\n"))
1行目: 一行目: Pythonでテキストを読みます。
2行目: 二行目: 改行や空白を含みます。
ファイル位置は進むため、同じ行を繰り返し読むにはseek(0)で先頭に戻す必要があります。
readlines()で行リストを取得
readlines()は全行をリストで返すため、インデックスでアクセスしたい場合に便利です。
ただしメモリ使用量に注意します。
with open("sample.txt", "r", encoding="utf-8") as f:
lines = f.readlines() # ["一行目...\n", "二行目...\n", ...]
print("行数:", len(lines))
print("2行目の生データ(改行含む):", repr(lines[1]))
行数: 3
2行目の生データ(改行含む): '二行目: 改行や空白を含みます。 \n'
改行は要素に含まれるため、必要に応じてrstrip(“\n”)を適用してください。
大量行ならfor
ループで逐次処理する方が安全です。
文字コードと改行の扱い
文字化けと余計な改行は初心者のつまずきポイントです。
encodingとnewlineの2つを意識するだけで多くの問題を回避できます。
encodingを指定して開く(UTF-8推奨)
Pythonでテキストを開く際は、基本的にencoding=”utf-8″を明示するのが安全です。
OS依存のデフォルトエンコーディングに左右されず、国際化にも強いです。
# 文字化け対策: UTF-8 を明示
with open("sample.txt", "r", encoding="utf-8") as f:
print(f.read())
一行目: Pythonでテキストを読みます。
二行目: 改行や空白を含みます。
三行目: 終わり。
既存ファイルがShift_JISなど別エンコーディングの場合はencoding="cp932"
(Windowsの日本語環境)などに変更します。
不明な場合でも当て推量の自動判定より、まずは作成元のエンコーディング情報を確認するのが確実です。
改行を除くstrip()の使い方
末尾の改行だけを消したいなら strip() ではなく rstrip(“\n”) を使うのが安全です。
strip()
は前後の空白やタブも消すため、データの末尾スペースが必要な場合に失われます。
s1 = "末尾にスペースあり \n" # 末尾スペース + 改行
print("strip:", repr(s1.strip())) # 前後の空白をすべて削除
print("rstrip(\"\\n\"):", repr(s1.rstrip("\n"))) # 改行のみ削除
strip: '末尾にスペースあり'
rstrip("\n"): '末尾にスペースあり '
データの空白は意味を持つことが多いため、必要最小限の削除を心がけるとよいです。
改行を含めて読むときの注意(newline)
open()のnewline引数は「改行の取り扱い」を制御します。
既定値None
ではユニバーサル改行が有効で、\r\n
や\r
も\n
に正規化されます。
表: newlineパラメータの挙動
newline | 読み込み時の挙動 |
---|---|
None(既定) | 改行は全て\nに変換される(ユニバーサル改行) |
“”(空文字) | 改行を変換せず、そのまま保持する |
“\n” 等 | 指定したもののみ改行として扱う |
# 改行をそのまま保持したい場合(newline="")
with open("sample.txt", "r", encoding="utf-8", newline="") as f:
raw = f.readlines()
print("raw[0]の末尾バイト表現:", [hex(ord(c)) for c in raw[0][-2:]]) # 例示: 改行の生データ
出力例(環境やファイルにより異なる):
raw[0]の末尾バイト表現: ['0x0a'] # \n の場合。CRLFなら ['0x0d','0x0a']
改行コードをそのまま扱いたい場合は newline=”” を指定すると確実です。
エラーと大きいファイルへの対応
運用時には、「存在しないファイルへの対処」と「メモリに優しい読み方」が重要になります。
UTF-8のBOMも地味にハマりポイントです。
FileNotFoundErrorの簡単な対処
存在しないパスを開くと FileNotFoundError が発生します。
まずはパス確認、必要なら例外をキャッチして丁寧に案内します。
from pathlib import Path
path = Path("not_exists.txt")
try:
with path.open("r", encoding="utf-8") as f:
print(f.read())
except FileNotFoundError:
# ユーザーに次の行動を案内する
print(f"ファイルが見つかりません: {path.resolve()}")
print("パスが正しいか、カレントディレクトリを確認してください。")
ファイルが見つかりません: /Users/you/work/not_exists.txt
パスが正しいか、カレントディレクトリを確認してください。
例外を握りつぶすのはNGです。
最低限、原因の手がかり(探した絶対パスや権限)を出力しましょう。
大きいファイルは逐次処理で読む
巨大ファイルは「一気にread」せず、forループやチャンク分割で逐次処理します。
# 1) 行ごとの逐次処理(最も簡単でメモリ効率が良い)
line_count = 0
with open("huge.txt", "r", encoding="utf-8") as f:
for _ in f: # 1行ずつ読み進める
line_count += 1
print("行数(概数):", line_count)
# 2) 固定サイズでチャンク読み(バイナリ/テキストの両方で応用可)
# テキストで境界を跨ぐと1行が分断されるため、用途に応じてラインバッファを使う
def read_in_chunks(path, chunk_size=1024 * 1024):
with open(path, "r", encoding="utf-8", newline="") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
yield chunk
total_chars = 0
for chunk in read_in_chunks("huge.txt"):
total_chars += len(chunk)
print("文字数(概数):", total_chars)
行数(概数): 1234567
文字数(概数): 987654321
行単位の逐次処理がもっとも手堅く、多くのケースで十分高速です。
チャンク読みはログの一括検索など特定用途向けに使います。
BOM付きUTF-8を読む(utf-8-sig)
BOM(Byte Order Mark)付きUTF-8は先頭に不可視文字(\ufeff)が入るため、1行目の先頭に謎の文字が混ざる原因になります。
encoding="utf-8-sig"
を指定するとBOMを自動で取り除いてくれます。
# 先頭に BOM がある UTF-8 ファイルの安全な開き方
with open("bom_utf8.txt", "r", encoding="utf-8-sig") as f:
first = f.readline()
print("先頭行:", repr(first)) # \ufeff が含まれないことを確認
先頭行: 'タイトル,日付,本文\n'
もしencoding=”utf-8″で開くと、'\ufeffタイトル...'
のように不可視文字が含まれ、ヘッダ名の一致判定などで不具合になります。
外部由来のCSVなどはutf-8-sigをまず試すのが安全です。
まとめ
本記事では、Pythonでテキストファイルを読み込むための基本から実践的な注意点までを整理しました。
日常利用ではwith構文とencoding=”utf-8″の明示を標準形にし、行処理にはfor
ループを使うことで、メモリ効率と可読性を両立できます。
改行の扱いにはrstrip("\n")
やnewline
を適切に使い分け、パス指定はpathlib.Path
で明確にしましょう。
さらに、FileNotFoundErrorのハンドリングとBOM付きUTF-8(utf-8-sig)への対応を押さえておくと、実務でも安定して動くコードになります。