YutaKaのPython教室

Python の文法やライブラリ、API、環境構築について画像・動画・ソースコード付きで徹底解説!

Python テキストファイル読み込み・テキスト処理まとめ

Pythonでは、始めからインストールされている標準モジュールを使うだけで、簡単にテキストファイルを読み込むことができます。

しかし、実際にテキストファイルを読み込もうとすると、次のような問題に直面することも…

  • ファイルの読み込みってどうやるんだっけ?
  • エンコーディングのエラーがでた!
  • テキストの出力方法にも種類があって、使い分けがよくわからない!
  • 読み込み後の処理でいつも戸惑う…

そこで、この記事ではPythonでのテキストファイル読み込み、よく使うテキスト処理について、図解付きで徹底解説しています!

テキスト読み込みの基本の流れ

Pythonでのテキスト読み込みの基本の流れは次の通りです。

  1. open()関数などでテキストファイルを開く
  2. .read()メソッド等でファイルの中身を読み込む

ファイルの開き方や読み込み方法で、細かな設定は必要ですが、大きな流れは基本的に上記の通りです。

以下では、テキストファイルの開き方、読み込み方について、順番に詳しく解説していきます。

ファイルを開く

ファイルを開くには、Pythonの組み込み関数open()を使用します。

引数で開きたいファイルのパスを指定すればOKです。

  • open(ファイルのパス)
    • Ex1:作業フォルダ内のファイルを相対パスで指定 ⇒ open(ファイル名)
    • Ex2:絶対パスでファイルを指定 ⇒ open("C:\Users\YutaKa\Documents\ファイル名")

open()でファイルを開く場合、次の2パターンがあります。

  1. open()関数で開いて、.close()で閉じる
  2. with open()の構文でファイルを開く(ファイルは自動で閉じられる)

open()関数でファイルを開く場合には、閉じ忘れに注意する必要がありますが、with open構文であれば閉じ忘れの心配はありません。

open()関数で開く例、with open()構文で開く例の順番で実行例を見てみましょう。

open()関数で開く

まずは、open()関数でファイルを開く例を見てみます。

ここでは、作業フォルダ内にsample.txtがあるものとして、一連の処理を記述してみます。

f = open("sample.txt")

# テキスト読み込みなどの処理文

f.close()

この例は、次のような処理フローになっています:

  1. open()関数で開いたファイルを変数fに格納
  2. 何かしらの処理をする
  3. f.close()でファイルを閉じる

open()関数開いたファイルは自動では閉じられません。

最後にf.close()でファイルを閉じるのを忘れないように気を付けましょう。

with open()構文で開く

次にwith open()構文でファイルを開く方法を紹介します。

with open()構文でファイルを開くと、withブロックが終わった後に自動でファイルを閉じてくれます。

ファイルの閉じ忘れの心配がなくなるので、with open()構文はぜひ覚えてほしいテクニックです。

with open("sample.txt") as f:
    # 処理文

この例は、次のような処理フローになっています。

  1. with open()構文で、ファイルを変数fとして開く
  2. 何かしらの処理をする
  3. 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のリストができあがりましたね。

  • 【参考】文末の改行文字の削除方法については、次の記事で解説しています。
≫【コピペOK!】改行を削除するPythonスクリプト
pyhonでテキストファイルを読み込んだ時に、改行コード\nが残って困ってしまうことがありますね。今回はテキストデータから改行コードを削除する方法を3つ紹介します。①文字列の置換メソッド:replace()で削除、②reモジュールの置換メソッド:re.subで削除、③文字列の末尾削除メソッド:rstrip()で削除。応用例として、クリップボードにコピーしたテキストから、改行コードを削除する効率化技も紹介しています。
www.yutaka-note.com/entry/linebreak
 
指定した文字数のみ読み込み

指定した文字数ずつ読み込みたい場合は、.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="")
# 一行目です。
# 二行目です。
# 三行目です。

シンプルな記述で、ファイルの一行目から三行目まで出力されましたね。

これでテキストファイルの読み込みについての処理については網羅できたと思います。

よく使うテキスト処理まとめ

以下では、実務上よく使うテキスト処理について、汎用性の高いものをまとめます。

  1. print()関数の改行調整
  2. テキストをスペース、カンマで分割
  3. テキストの結合
  4. 特定の文字で始まる/終わるか判定
  5. 特定の文字を含むか判定
  6. 正規表現で特定のパターンを抽出

実際には、これらに加えて複雑な処理を追加することが多いですが、ここでは基本的なものを整理しています。

print()関数の改行調整

テキストファイルをprint()関数で出力する際の改行に関する注意点について解説します。

f.readline()などで読み込んだテキストをprint()関数で出力すると、行と行の間に不要な空欄行が出力されることがあります。

with open("sample.txt", encoding="UTF-8") as f:
    for line in f:
        print(line)
# 一行目です。
                        # ← 不要な空欄行
# 二行目です。
                        # ← 不要な空欄行
# 三行目です。

これは、各行で次の理由で各行に二重で改行が適用されてしまうためです。

  1. print()関数は、実行ごとに自動で改行(改行1個目)
  2. 読み取りデータ行末の\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)
'さ-し-す-せ-そ'
  • 【参考】文字列の結合については、次の記事で詳しく解説しています。
≫Python 文字列の分割方法まとめ|図解付で分かりやすく解説
文字列の分割は、文字列の解析やデータ処理などで頻繁に行われる作業の一つですね。Pythonには、文字列を簡単に分割するための機能が豊富に用意されています。しかし、実際に文字列の分割を行おうとすると、次のような課題に直面することも…。① 特定の文字でテキストを分割する方法は?② テキストを行ごとに分割する方法は?③ 正規表現を使って複雑な分割処理を行いたい! この記事では、Pythonの文字列分割について図解付きでわかりやすく解説していきます。
www.yutaka-note.com/entry/bf_split
 

テキストをスペース、カンマで分割

読み込んだテキストを、スペースやカンマで分割する処理をすることもよくあります。

テキストの分割には、.split()メソッドを使用します。

  • 空白文字で分割:"文字列".split()
  • 分割文字を指定:"文字列".split("分割文字")
    • Ex) カンマで分割:"文字列".split(",")

次のサンプルファイルで実行例を確認してみます。

各行を読み込んで、料理名と何人前で分割してみます。

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円']

このパターンを使えば、テキストを読み取りながら様々な文字で分割することが可能です。

  • 【参考】テキスト分割については、次の記事で詳しく解説しています。
≫Python 文字列の分割方法まとめ|図解付で分かりやすく解説
文字列の分割は、文字列の解析やデータ処理などで頻繁に行われる作業の一つですね。Pythonには、文字列を簡単に分割するための機能が豊富に用意されています。しかし、実際に文字列の分割を行おうとすると、次のような課題に直面することも…。① 特定の文字でテキストを分割する方法は?② テキストを行ごとに分割する方法は?③ 正規表現を使って複雑な分割処理を行いたい! この記事では、Pythonの文字列分割について図解付きでわかりやすく解説していきます。
www.yutaka-note.com/entry/bf_split
 

特定の文字で始まるか判定

特定の文字列で始まるか判定する場合には、.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}}

正規表現と組み合わせると簡単にデータの抽出を行うことができますね。

正規表現に慣れていない方は、次の記事でわかりやすく解説しているので参考にしてください。

≫Python正規表現パターンを図解&サンプルで本当にわかりやすく解説
Pythonのreモジュールで正規表現パターンを作成する際に重要な3つのポイントを解説します。①特定の文字の繰り返しを指定 ②数値や文字、空白など条件による文字条件の指定 ③グループ化によるパターン内の特定部分の抽出
www.yutaka-note.com/entry/regex_01
 
≫Python 正規表現の検索を本当にわかりやすく解説
Pythonで正規表現を使用して、パターン検索する方法をわかりやすく解説しています。① 検索メソッド(関数)の実行方法② 各メソッドの紹介(単独検索search()、全体検索findallなど)③ 検索結果の出力であるMatchオブジェクトの内容
www.yutaka-note.com/entry/regex_02
 

また、テキストファイルを辞書型に成形できれば、その後は簡単にpandasDataFrameに変換、データ分析につなげられます。

import pandas as pd
df = pd.DataFrame.from_dict(my_dict).T
df

辞書型からのDataFrameの生成方法がわからない場合は、次の記事でわかりやすく解説しているので参考にしてください。

≫pandas 辞書型からDataFrameを生成|インデックスとコラムの設定も!
pandasでは、辞書型からデータフレームを生成することもできます。しかし、pandasの操作に慣れていないうちは、ちょっとした操作も難しいですよね。この記事では、①辞書型からデータフレームを生成する方法、②辞書のキーをインデックス名、コラム名それぞれに設定する方法、③DataFrame()とDataFrame.from_dict()の違いをサンプルコード付きで紹介!
www.yutaka-note.com/entry/pandas_dict
 

オススメ|データ分析の勉強方法

今回はPythonでテキストファイルを読み込む方法について解説しました。

データ分析初心者の方にはこちらの記事もおススメです。

≫独学でデータ分析を勉強するオススメ学習本
独学でのpythonデータ分析勉強に役立ったおススメ書籍を紹介していきます。業務でそれなりにデータ分析を行えるまで、いろいろな試行錯誤をしてきましたが、もし自分が今ゼロから勉強する立場ならどうするのがいいのか考えてみました。以下では、入門書、個別モジュール用、実践用の3つの視点でおススメ本を紹介していきます。
www.yutaka-note.com/entry/data_analysis
 

Pythonで作業の効率化を目指している方には、次の記事がおススメです。

≫【レビュー】退屈なことはPythonにやらせよう | 単純作業は自動化
名著「退屈なことはPythonにやらせよう 」をレビュー!単純作業を自動化して、自分が本当にしたいことのために時間を確保していこう!所要時間やできるようになったことを紹介!この本を参考にして作成した、自作自動化スクリプトも紹介しています!
www.yutaka-note.com/entry/python_jido
 
≫【レビュー】Python自動処理 全部入り。 | 即効性重視!Pythonによる自動化事例集!
今回は、Pythonの作業自動処理の解説本『Python自動処理全部入り』をレビュー!この本は、特定の作業に特化した即効性の重視の自動化解説本です。よくある作業から自動化しやすい作業を抽出して、それらの自動化を集中的に解説した本という印象です。本の中に自分のニーズに合った自動化処理が見つかれば、その日からすぐ使える事例集のような印象です。
www.yutaka-note.com/entry/python_jido_zenbu