Pythonでは、始めからインストールされている標準モジュールを使うだけで、簡単にテキストファイルを読み込むことができます。
しかし、実際にテキストファイルを読み込もうとすると、次のような問題に直面することも…
- ファイルの読み込みってどうやるんだっけ?
- エンコーディングのエラーがでた!
- テキストの出力方法にも種類があって、使い分けがよくわからない!
- 読み込み後の処理でいつも戸惑う…
そこで、この記事ではPythonでのテキストファイル読み込み、よく使うテキスト処理について、図解付きで徹底解説しています!
テキスト読み込みの基本の流れ
Pythonでのテキスト読み込みの基本の流れは次の通りです。
open()
関数などでテキストファイルを開く.read()
メソッド等でファイルの中身を読み込む
ファイルの開き方や読み込み方法で、細かな設定は必要ですが、大きな流れは基本的に上記の通りです。
以下では、テキストファイルの開き方、読み込み方について、順番に詳しく解説していきます。
ファイルを開く
ファイルを開くには、Pythonの組み込み関数open()
を使用します。
引数で開きたいファイルのパスを指定すればOKです。
open(ファイルのパス)
- Ex1:作業フォルダ内のファイルを相対パスで指定 ⇒
open(ファイル名)
- Ex2:絶対パスでファイルを指定 ⇒
open("C:\Users\YutaKa\Documents\ファイル名")
- Ex1:作業フォルダ内のファイルを相対パスで指定 ⇒
open()
でファイルを開く場合、次の2パターンがあります。
open()
関数で開いて、.close()
で閉じるwith open()
の構文でファイルを開く(ファイルは自動で閉じられる)
open()
関数でファイルを開く場合には、閉じ忘れに注意する必要がありますが、with open
構文であれば閉じ忘れの心配はありません。
open()
関数で開く例、with open()
構文で開く例の順番で実行例を見てみましょう。
open()関数で開く
まずは、open()
関数でファイルを開く例を見てみます。
ここでは、作業フォルダ内にsample.txt
があるものとして、一連の処理を記述してみます。
f = open("sample.txt")
# テキスト読み込みなどの処理文
f.close()
この例は、次のような処理フローになっています:
open()
関数で開いたファイルを変数f
に格納- 何かしらの処理をする
f.close()
でファイルを閉じる
open()
関数開いたファイルは自動では閉じられません。
最後にf.close()
でファイルを閉じるのを忘れないように気を付けましょう。
with open()構文で開く
次にwith open()
構文でファイルを開く方法を紹介します。
with open()
構文でファイルを開くと、with
ブロックが終わった後に自動でファイルを閉じてくれます。
ファイルの閉じ忘れの心配がなくなるので、with open()
構文はぜひ覚えてほしいテクニックです。
with open("sample.txt") as f:
# 処理文
この例は、次のような処理フローになっています。
with open()
構文で、ファイルを変数f
として開く- 何かしらの処理をする
with
構文から抜けると自動で、ファイルが閉じられる
with open
構文はファイルの閉じ忘れがなくて便利です。
一方、ファイルを閉じてしまうので、プログラムの別の場所で再度ファイルを利用することはできません。
状況に応じて、open()
関数とwith open()
構文を使い分けましょう。
エンコーディングの指定
ファイル読み込みの際によくあるトラブルは、エンコードに関するものです。
誤解を恐れずに超ざっくりエンコードを説明すると、次のようなイメージです。
- そもそもPC上のデータは、0と1で記録されている
- 0と1のデータを文字列に変換するときに特定のルールに従う必要がある
- このルールの種類がエンコードと呼ばれるもの
図にすると次のようなイメージです。
Pythonのopen()
関数では、OSに応じたエンコーディングが自動で選ばれます(個人個人の環境によって上の表以外になる場合もあります。)。
OS | エンコーディング |
---|---|
Windows | cp932 |
macOX | UTF-8 |
Linux | UTF-8 |
例えば、開こうとしているファイルがUTF-8
のルールで記述されているのに、cp932
のルールで開こうとすると次のような問題が起こります。
- ファイルは開けるが、違うルールで変換しているので文字化けする
cp932
のルールでは解読できない文字があって、エラーを出す
Windowsのメモ帳であれば、ウィンドウ右下でエンコードが確認できます。
UTF-8
でエンコードされているテキストファイルをWindows
のデフォルト設定(cp932
)で開いた際のエラー例を見てみましょう。
with open("sample.txt") as f:
text = f.read()
# UnicodeDecodeError: 'cp932' codec can't decode byte 0xef in position 25: illegal multibyte sequence
cp932
では、読めない文字があるとエラーが出てしまいました。
こういった場合は、open()
関数の引数enconding
で正しいエンコードを指定します。
encoding="エンコード名"
今回の場合は、encoding="UTF-8"
を指定します。
with open("sample.txt", encoding="UTF-8") as f:
text = f.read()
# エラーが出ずにファイルを読み込めた
テキストを読み込む
open()
でファイルを開いた後は、.read()
メソッドなどでファイルを読み込みます。
基本的な読み取り方法は次の通りです。
読み込み方法 | メソッド | コメント |
---|---|---|
ファイル全体(文字列) | .read() |
ファイルの内容全体を文字列で一括取得 |
ファイル全体(行ごとのリスト) | .readlines() |
[一行目, 二行目,…] 形式のリスト |
指定した文字数のみ | .read(文字数) |
数文字ずつ取得したい場合に便利 |
一行ずつ読み込み | .readline() or for 文で読み込み |
一行ずつ読み取りたい場合に便利 |
例えばファイルを変数f
で開いている場合は、次のようにメソッドを呼び出して文字列を読み込みます。
text = f.read()
この例では、ファイルの内容全体が文字列として変数text
に格納されます。
次のサンプルファイルを使って、各読み込み方法の実行例を確認してみましょう。
ファイル全体読み込み(文字列)
ファイル全体を文字列で一括取得したい場合は、.read()
メソッドを使用します。
text = f.read()
サンプルファイルで実行例を確認してみましょう。
with open("sample.txt", encoding="UTF-8") as f:
text = f.read()
text
# '一行目です。\n二行目です。\n三行目です。'
無事、ファイルの中身が取得できましたね。
改行コード\n
に慣れていない方のために補足です。
変数text
に格納されているときは、改行は改行コード\n
で記述されています。
一方、print()
関数で出力すると改行コードは\n
に展開(変換)されます。
print(text)
# 一行目です。
# 二行目です。
# 三行目です。
print()
関数で改行コードが展開されることを覚えておくと、\n
で混乱することもなくなると思います。
ファイル全体読み込み(リスト)
ファイル全体を行ごとのリストで一括取得したい場合は、.readlines()
メソッドを使用します。
text_list = f.readlines()
- 結果 ⇒
["一行目", "二行目", "三行目", …]
- 結果 ⇒
サンプルファイルで実行例を確認してみましょう。
with open("sample.txt", encoding="UTF-8") as f:
text_list = f.readlines()
text_list
# ['一行目です。\n', '二行目です。\n', '三行目です。']
サンプルファイルは、3行のなので要素数が3のリストができあがりましたね。
- 【参考】文末の改行文字の削除方法については、次の記事で解説しています。
指定した文字数のみ読み込み
指定した文字数ずつ読み込みたい場合は、.readl()
メソッドに文字数を渡します。
text = f.read(指定文字数)
ファイルを開いたまま、.read(指定文字数)
を繰り返すと、読み込み開始位置が指定文字数
ずつずれていきます。
そのため、.read(指定文字数)
を繰り返すことで、指定文字数ずつ読み込めます。
サンプルファイルで実行例を確認してみましょう。
with open("sample.txt", encoding="UTF-8") as f:
text1 = f.read(1)
text2 = f.read(2)
text3 = f.read(3)
print(text1)
print(text2)
print(text3)
上記の例では、3文字ずつ読み取られていますね。
また、ファイルの最後に到達済みの場合は、""(空文字)
を返します。
for
文で繰り返しテキストを読み込み、ファイルの最後に到達する例を見てみます。
my_list = []
with open("sample.txt", encoding="UTF-8") as f:
for i in range(7):
text = f.read(5)
my_list.append(text)
my_list
# ['一行目です',
# '。\n二行目',
# 'です。\n三',
# '行目です。',
# '',
# '',
# '']
最後の3回は文末に到達して空文字が出力されていますね。
for
文やwhile
文で回したい場合は、""(空文字)
で条件を設定すると良いです。
while
文で""
を利用してループを抜ける例を見てみます。
my_list = []
with open("sample.txt", encoding="UTF-8") as f:
while text := f.read(10): # :=は代入演算子(代入してからwhileで評価される)
my_list.append(text)
my_list
# ['一行目です。\n二行目', 'です。\n三行目です。']
while
文の条件判定で、""
がFalse
として扱われることを利用してループを抜けています。
一行ずつ読み込む
ファイルを一行ずつ読み込む場合は、.readline()
メソッドを使用します。
line = f.readline()
ファイルを開いたまま、.readline()
を繰り返すと一行ずつ読み込みが行われます。
.read(指定文字数)
と同じように、ファイルの末尾に到達すると""(空文字)
を返します。
サンプルファイルで実行例を確認してみましょう。
my_list = []
with open("sample.txt", encoding="UTF-8") as f:
for i in range(10):
line = f.readline()
my_list.append(line)
my_list
# ['一行目です。\n', '二行目です。\n', '三行目です。', '', '', '', '', '', '', '']
文末に到達すると空文字が出力されていますね。
while
文で""
を利用してループを抜ける例を見てみます。
my_list = []
with open("sample.txt", encoding="UTF-8") as f:
while line := f.readline():
my_list.append(line)
my_list
# ['一行目です。\n', '二行目です。\n', '三行目です。']
for分で一行ずつ読み込む
open()
で開いたファイルを一行ずつ読み込む場合は、for
文を使用してシンプルに実行することも可能です。
次の形式で記述すると、ファイルの冒頭から末尾まで一行ずつ読み取ることができます。
my_list = []
with open(ファイル名) as f:
for line in f:
# 処理文
この記述方法では、次のような挙動になります。
- 各
for
ループでファイルの中身が一行ずつ変数line
に読み込まれる - 文末に到達すると
for
ループを抜ける
for
文を抜ける条件を書く必要がないという点では、.readline()
よりも便利ですね。
サンプルファイルで実行例を確認してみましょう。
with open("sample.txt", encoding="UTF-8") as f:
for line in f:
print(line, end="")
# 一行目です。
# 二行目です。
# 三行目です。
シンプルな記述で、ファイルの一行目から三行目まで出力されましたね。
これでテキストファイルの読み込みについての処理については網羅できたと思います。
よく使うテキスト処理まとめ
以下では、実務上よく使うテキスト処理について、汎用性の高いものをまとめます。
print()
関数の改行調整- テキストをスペース、カンマで分割
- テキストの結合
- 特定の文字で始まる/終わるか判定
- 特定の文字を含むか判定
- 正規表現で特定のパターンを抽出
実際には、これらに加えて複雑な処理を追加することが多いですが、ここでは基本的なものを整理しています。
print()関数の改行調整
テキストファイルをprint()
関数で出力する際の改行に関する注意点について解説します。
f.readline()
などで読み込んだテキストをprint()
関数で出力すると、行と行の間に不要な空欄行が出力されることがあります。
with open("sample.txt", encoding="UTF-8") as f:
for line in f:
print(line)
# 一行目です。
# ← 不要な空欄行
# 二行目です。
# ← 不要な空欄行
# 三行目です。
これは、各行で次の理由で各行に二重で改行が適用されてしまうためです。
print()
関数は、実行ごとに自動で改行(改行1個目)- 読み取りデータ行末の
\n
改行コードで改行(改行2個目)
不要な空欄行を避けるためには、print()
関数実行時の改行を省く設定にするのがおすすめです。
次のようにend
引数に空文字を適用しましょう。
print(出力内容, end="")
これで不要な空欄行を避けることができます。
with open("sample.txt", encoding="UTF-8") as f:
for line in f:
print(line, end="")
# 一行目です。
# 二行目です。
# 三行目です。
テキストの結合
読み込んだ文字列は、+
で結合できます。
s1 = "あいう"
s2 = "えお"
s1+s2
# "あいうえお"
文字列のリストを結合する場合は、.join()メソッドを使用します。
"結合文字".join([文字列のリスト])
サンプルコードで挙動を確認してみましょう。
s = ["さ", "し", "す", "せ", "そ"]
# "_"で結合
"_".join(s)
'さ_し_す_せ_そ'
# " "で結合
" ".join(s)
'さ し す せ そ'
# "-"で結合
"-".join(s)
'さ-し-す-せ-そ'
- 【参考】文字列の結合については、次の記事で詳しく解説しています。
テキストをスペース、カンマで分割
読み込んだテキストを、スペースやカンマで分割する処理をすることもよくあります。
テキストの分割には、.split()
メソッドを使用します。
- 空白文字で分割:
"文字列".split()
- 分割文字を指定:
"文字列".split("分割文字")
- Ex) カンマで分割:
"文字列".split(",")
- Ex) カンマで分割:
次のサンプルファイルで実行例を確認してみます。
各行を読み込んで、料理名と何人前で分割してみます。
with open("sample2.txt", encoding="UTF-8") as f:
for line in f:
my_list = line.split()
print(my_list)
# ['お寿司', '10人前', '10000円']
# ['焼き肉', '5人前', '5000円']
# ['肉野菜炒め', '10人前', '2000円']
# ['おにぎり', '10人前', '1000円']
このパターンを使えば、テキストを読み取りながら様々な文字で分割することが可能です。
- 【参考】テキスト分割については、次の記事で詳しく解説しています。
特定の文字で始まるか判定
特定の文字列で始まるか判定する場合には、.startswith()
メソッドを使用します。
"文字列".startswith("対象文字")
"文字列"
が"対象文字"
で始まる場合はTrue
を、そうでない場合はFalse
を返します。
サンプルファイルで、"お"
から始まる行だけ出力してみましょう。
with open("sample2.txt", encoding="UTF-8") as f:
for line in f:
if line.startswith("お"):
print(line, end="")
# お寿司 10人前 10000円
# おにぎり 10人前 1000円
特定の文字を含むか判定
特定の文字列を含むか判定する場合には、in
演算子を使用します。
"対象文字" in "文字列"
"対象文字"
が"文字列"
に含まれる場合はTrue
を、そうでない場合はFalse
を返します。
サンプルファイルで、"肉"
を含む行を出力してみましょう。
with open("sample2.txt", encoding="UTF-8") as f:
for line in f:
if "肉" in line:
print(line, end="")
# 焼き肉 5人前 5000円
# 肉野菜炒め 10人前 2000円
正規表現で特定のパターンを抽出
読み込み文字列から複雑な抽出をしたい場合は、正規表現を使用しましょう。
正規表現で「食事名 個数 金額」のパターンを作って、サンプルファイルからデータを抽出、辞書型に成形してみます。
import re
p = re.compile("(\w+)\s(\d+)\w+\s(\d+)\w+")
my_dict = {}
with open("sample2.txt", encoding="UTF-8") as f:
for line in f:
m = p.search(line)
food = m.group(1)
num = int(m.group(2))
price = int(m.group(3))
my_dict[food] = {"Num": num, "Price": price}
my_dict
# {'お寿司': {'Num': 10, 'Price': 10000},
# '焼き肉': {'Num': 5, 'Price': 5000},
# '肉野菜炒め': {'Num': 10, 'Price': 2000},
# 'おにぎり': {'Num': 10, 'Price': 1000}}
正規表現と組み合わせると簡単にデータの抽出を行うことができますね。
正規表現に慣れていない方は、次の記事でわかりやすく解説しているので参考にしてください。
また、テキストファイルを辞書型に成形できれば、その後は簡単にpandas
のDataFrame
に変換、データ分析につなげられます。
import pandas as pd
df = pd.DataFrame.from_dict(my_dict).T
df
辞書型からのDataFrame
の生成方法がわからない場合は、次の記事でわかりやすく解説しているので参考にしてください。
オススメ|データ分析の勉強方法
今回はPythonでテキストファイルを読み込む方法について解説しました。
データ分析初心者の方にはこちらの記事もおススメです。
Pythonで作業の効率化を目指している方には、次の記事がおススメです。