PR

【Python】ファイル操作―書き込み/読み込みを3分で

Python

Pythonにおけるファイル操作の基本を初心者向けに1からわかりやすく解説します。

ファイル操作とは、テキストやバイナリ(画像、音楽、ビデオなど)ファイルの読み書き、ファイル名の変更、ファイルの移動、そしてディレクトリの作成や削除といった操作を含みます。これらはプログラミングの世界では日常的に行われ、重要なスキルとなります。

# ファイルを読み込むために open 関数を使用
file = open('sample.txt', 'r') 

# ファイルの内容を表示
print(file.read())

# ファイルを閉じる
file.close()

このページでは、Pythonでの基本的なファイル操作の理解と実践を理解できるように各種様々な具体例をサンプルコードを用いながらご説明します。

このページで学べる内容
  • ファイルオブジェクトとは?
  • ファイルの読み込み
    • 'open' 関数の使用方法
  • ファイルの読み込みと書き込み
    • writeメソッド
    • readメソッド
  • ファイルのクローズ
    • 'close' 関数の使用

Pythonエンジニアを目指す方であれば知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。

参考 Pythonの基本的な書き方・構文ルール

スポンサーリンク

Python:ファイルオブジェクト

まずは、Pythonにおけるファイル操作を理解するうえで重要となる「ファイルオブジェクト」という概念についてご説明します。

ファイルオブジェクトとは、Pythonにおける特別な種類のオブジェクトで、具体的にはファイルや他の種類のストリーム(入出力ストリームなど)を操作するために使用されます。

Python初心者向けに比喩的な表現で説明すると、ファイルオブジェクトとはPythonのプログラム上に生成された操作対象のファイルのクローンのようなものということができます。

Python ファイルオブジェクト
図1:Python「ファイルオブジェクト」
# ファイルを新規作成
file = open('sample.txt', 'r')

上記のコードでは、sample.txtという名前のファイルを読み取りモードで開き、その結果をfileという名前のファイルオブジェクトに保存。

つまり、sample.txt というクローンを fileという名称で誕生させたことになります。

Pythonでファイル操作を行う際には、このファイルオブジェクトに対して読み込みや書き込みといった操作を行うのですが、このクローンを通じて実体のファイルに行った処理が反映されるという仕組み。

この前提を押さえたうえで具体的にファイル操作の中身を解説していきます。

【詳細解説】ファイルオブジェクトとは?

ファイルオブジェクトは、ある意味で操作対象のファイルの「クローン」や「代理」と考えることができますが、これは比喩的な表現であり、技術的な観点からは、ファイルオブジェクトはファイルへの「参照」または「ハンドル」と理解するのがより正しいです。

ファイルオブジェクトは、ディスク上の実際のファイルと対話するためのインターフェイスを提供するのが役割を担います。これにより、Pythonのコード内からファイルの内容を読み込んだり、新たな内容を書き込んだり、ファイルを閉じたりすることが可能になるということ。

open()関数を呼び出すと、指定したパスにあるファイルに対する接続が開かれ、その接続を制御するためのファイルオブジェクトが生成されます。このファイルオブジェクトを通じて、Pythonプログラムはファイルに読み書きすることができるようになるということを理解しましょう。

より技術的に正しい表現でファイルオブジェクトを説明すると・・・
→ファイルオブジェクトとは「プログラムがファイルを操作するための「ブリッジ」または「ゲートウェイ」の役割を果たすもの」

参考 Python:オブジェクトとは?

Pyhon:open関数(ファイルを開く)

open()関数はPythonの組み込み関数で、ファイルを開いて操作するためのファイルオブジェクトを生成します。以下に基本的な構文を示します。

open関数:構文ルール
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

以下のサンプルコードを例に1つ1つのオプションについて解説していきます。

# ファイルを読み取りモードで開く
file = open('sample.txt', 'r')
print(file.read())
file.close()

# ファイルを書き込みモードで開く(既存の内容は上書き)
file = open('sample.txt', 'w')
file.write('Hello, World!')
file.close()

# ファイルを追記モードで開く
file = open('sample.txt', 'a')
file.write('Hello again!')
file.close()

# バイナリモードでファイルを開く
file = open('image.jpg', 'rb')
data = file.read()
file.close()

参考 print関数

Python:open(file)

この引数は必須の引数で、開くファイルの名前またはパスを指定します。先ほどの例では、「sample.txt」というファイル名を指定しています。

# ファイルを読み取りモードで開く
file = open('sample.txt', 'r')
print(file.read())
file.close()

上記のコードを実行することで「sample.txt」というファイルが作成されます。

Python:open(mode)

2番目の引数では、ファイルを開くモードを指定します。デフォルトは 'r' で、これは読み取り専用モードを意味します。

他の主なモードには以下のものがあります。

モード説明
'r'ファイルを読み取り専用で開きます(デフォルト)。
'w'ファイルを書き込み専用で開きます。既存のファイルがある場合は内容を上書き。
ファイルが存在しない場合は新規に作成します。
'a'ファイルを追記モードで開きます。既存のファイルの末尾に新しいデータを追加。
ファイルが存在しない場合は新規に作成します。
'x'ファイルを排他的に作成します。すでにファイルが存在する場合はエラーを返します。
'b'バイナリモードでファイルを開きます。
このモードは 'r', 'w', 'a', 'x' と組み合わせて使用します。
't'テキストモードでファイルを開きます(デフォルト)。
このモードは 'r', 'w', 'a', 'x' と組み合わせて使用します。
'+'ファイルを読み書き両用で開きます。
'r', 'w', 'a' と組み合わせて使用します。

モードは簡単に言うと、「読み込み」なのか「書き込み」なのかを指定するものだと覚えておきましょう。

なお、複数のモードを組み合わせることが可能で、その際はそれらを連結した文字列を指定します。例えば、'rb'はバイナリ読み取りモード、'w+'は読み書き両用モード(既存の内容は消去)、'a+'は読み書き両用の追記モードを意味します。

# バイナリモードでファイルを開く
file = open('image.jpg', 'rb')
data = file.read()
file.close()

Python:open(encoding)

encoding引数は、テキストファイルを読み込む際や書き込む際にどの文字コードを使用するかを指定します。

Pythonのopen()関数では、encoding引数を省略した場合のデフォルトの文字エンコーディングはプラットフォームに依存します。通常はUTF-8が使われますが、WindowsではCP1252(Western European)が使われることもあります。

# ファイルを開く
file = open("sample.txt", mode="r", encoding="utf-8")

# ファイルの内容を表示する
for line in file:
    print(line.strip())

# ファイルを閉じる
file.close()

例えば、日本語を含むテキストファイルを開く場合、適切なエンコーディングを指定しないと文字化けが発生する可能性があります。日本語のテキストファイルはしばしばShift-JISやEUC-JPでエンコードされています。

エンコーディングは、省略するエンジニアの人もいますが、文字コードが異なると文字化けの原因となるためできるだけ指定するようにしましょう。

Python:open(errors)

errors引数は、エンコーディングやデコーディング中にエラーが発生したときのエラーハンドリング方法を指定します。文字エンコーディングの問題は、特定の文字が指定したエンコーディングスキームで表現できない場合や、ファイルから読み込んだバイトが有効な文字にデコードできない場合など、様々なシナリオで発生する可能性があります。

# ファイルを開く
file = open("sample.txt", mode="r", encoding="utf-8", errors="ignore")

# ファイルの内容を表示する
for line in file:
    print(line.strip())

# ファイルを閉じる
file.close()

このコードでは、'utf-8'でデコードできないバイトがあった場合でも、エラーは無視され、その部分は読み込み結果から省略されます。

errors引数で指定することができる値は以下の通り。

引数の値振る舞い
'strict'エンコーディング/デコーディングエラーが発生した場合、UnicodeErrorが発生します(デフォルト)。
'ignore'エンコーディング/デコーディングエラーを無視し、情報が失われる可能性があります。
'replace'有効な文字に変換できない場合や、エンコーディングできない場合は、代替文字(通常は'?')に置き換えます。
'backslashreplace'不適切な文字をPythonのバックスラッシュエスケープシーケンスに置き換えます。
'xmlcharrefreplace'不適切な文字を適切なXML文字参照に置き換えます。
'namereplace'不適切な文字をPythonの\N{...}エスケープに置き換えます。
表2:erros引数で指定する値

どのオプションを選ぶかは、特定の問題に対する最善の解決策を求めるときの具体的な状況によります。

Python:open(newline)

newline引数は、改行文字の制御を行うためのものです。

テキストファイルを扱う際、特に異なるオペレーティングシステム間での互換性を保つために重要な役割を果たします。これは、異なるシステムが異なる改行文字を使用するためです(Windowsでは\r\n、Unix/Linux/macOSでは\n)。

# ファイルを開く
file = open("sample.txt", mode="r", encoding="utf-8", newline="")

# ファイルの内容を表示する
for line in file:
    print(line.strip())

# ファイルを閉じる
file.close()

このコードはnewline=''を指定しているため、ファイルから行を読み込む時には'\n'、'\r'、'\r\n'をすべて改行と認識します。また、ファイルに行を書き込む時には'\n'をそのまま'\n'として書き込みます。

newline引数で指定できる値は以下の通り。

引数の値説明
Noneユニバーサル改行モードが有効になります。入力時にはすべての改行文字(\n\r\r\n)が\nに変換されます。出力時には\nがデフォルトの改行文字に変換されます。
''ユニバーサル改行モードが有効になります。しかし、書き込み('w'、'x'、'a')の際には改行の変換が行われません。つまり、\nはそのままの形で書き込まれます。
'\n''\r''\r\n'指定した改行文字のみが改行と認識され、他の改行文字は普通の文字として扱われます。
表3:newline引数

Python:open(buffering)

この引数はファイルのバッファリングポリシーを制御します。

# 行バッファリング
file = open('sample.txt', 'w', buffering=1)
file.write('Hello')
file.write('World')
file.close()

# バイトサイズでのバッファリング
file = open('sample.txt', 'w', buffering=4096)
file.write('Hello')
file.write('World')
file.close()

1つ目の例では、buffering=1 として行バッファリングを行っています。2つの write() メソッド呼び出しの間に改行文字がないため、HelloWorld というデータは1つの行としてバッファに蓄積されます。close() メソッドが呼び出されると、バッファ内のデータがファイルに書き込まれます。

2つ目の例では、buffering=4096 としてバイトサイズでのバッファリングを行っています。バッファサイズを 4096 バイトに指定しているため、データがバッファに 4096 バイト溜まるまでファイルに書き込まれません。write() メソッドの呼び出しによりバッファにデータが蓄積され、バッファサイズを超えた時点でデータがファイルに書き込まれます。

buffering 引数の値説明
0バッファリングを行わず、直接ファイルに書き込む。読み込み時はバッファリングされない。
1行バッファリングを行う。改行文字 \n までバッファにデータを蓄積し、改行文字が出現するとファイルに書き込む。
>1指定したバイト数のバッファサイズでバッファリングを行う。指定したバイト数分のデータがバッファに溜まると、ファイルに書き込まれる。

これらの値を buffering 引数に指定することで、ファイルの読み書き時のバッファリングの挙動を制御することができます。適切なバッファリング設定を選択することで、データの処理速度を最適化することができます。

バッファリングとは?

バッファリングとは、コンピュータのメモリ内に一時的にデータを蓄えることを指します。

ファイル操作の際に、特に大きなファイルを扱うときに、一度にすべてのデータを読み書きするのではなく、一部のデータをバッファ(一時記憶領域)に保存してから順次処理を行うと、全体のパフォーマンスを向上させることができます。

バッファリングの利点
  • 効率性: ハードドライブやSSDからデータを読み書きするのは、メモリ内での操作に比べて比較的遅いです。データを一度に大量に読み込み、それをメモリ上のバッファに保存しておくことで、データへのアクセスが速くなり、プログラムの効率が向上します。
  • 節約: バッファリングにより、ディスクからの読み書き回数が減少するため、ハードウェアの寿命を延ばすことができます。

buffering引数を使うと、バッファリングを無効にしたい場合や、行単位のバッファリングを行いたい場合、または特定のサイズのバッファを設定したい場合など、自分のニーズに合わせて設定することが可能です。しかし、通常はデフォルトのバッファリング設定で十分な場合が多いです。

Python:open(closefd)

この引数は、ファイルを閉じるときに元のファイルディスクリプタを閉じるべきかどうかを制御します。

  • closefd=True:デフォルトの振る舞いであり、ファイルを閉じる際にファイルディスクリプタも同時に閉じます。推奨はこちら。
  • closefd=False:ファイルを閉じる際にファイルディスクリプタを閉じません。ファイルディスクリプタは別途処理する必要があります。
# closefd=True(デフォルトの振る舞い)
file = open('sample.txt', 'r')
file.close()  # ファイルを閉じる際にファイルディスクリプタも閉じる

# closefd=False
fd = os.open('sample.txt', os.O_RDONLY)
file = open(fd, 'r', closefd=False)
file.close()  # ファイルを閉じるが、ファイルディスクリプタは閉じない
os.close(fd)  # 別途ファイルディスクリプタを閉じる
ファイルディスクリプタとは?

ファイルディスクリプタ(File Descriptor)は、Unix系オペレーティングシステム(LinuxやmacOSなど)で開いているファイルや他のI/Oリソース(ソケット、パイプ、デバイスなど)を参照するための抽象化されたハンドラです。これは一種の整数値で、オペレーティングシステムがそれぞれの開いたリソースを追跡するために使用します。

ただし、初心者がPythonでファイル操作を行う場合、通常はファイルディスクリプタを直接扱う必要はありません。その代わりに、Pythonのopen関数を使ってファイルを開き、返されるファイルオブジェクトを通じて読み書きすることが一般的です。

Python:open(opener)

この引数を使うと、ファイルを開くためのカスタムオープナーを指定できます。

openerはファイルパスとフラグを引数に取り、開かれたファイルのファイルディスクリプタを返す関数でなければなりません。オープナーが指定された場合、open()関数はデフォルトのオープナーをバイパスして、提供されたオープナーを使用します。

# カスタムのファイルオープナークラスの定義
class MyOpener:
    def open(self, file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
        # ファイルのオープン時に実行されるカスタムの処理
        # 例えば、ファイルのオープン前にログメッセージを出力するなど

        # デフォルトのファイルオープナーを呼び出してファイルをオープンする
        return open(file, mode, buffering, encoding, errors, newline, closefd)

# カスタムのファイルオープナーを使用してファイルをオープンする
file = open('sample.txt', 'r', opener=MyOpener())
data = file.read()
file.close()

参考 class / def文

Python:open関数のおさらい
  • pen関数は、ファイルを開くための組み込み関数。
    →指定された名前のファイルを開き、その内容にアクセスするための「ファイルオブジェクト」を生成。
file_object = open("file.txt", "r")

ファイルを開く方法(open関数)の利用方法を理解したところで、実際にそのファイルの読み込みや書き込み処理の方法を見ていきましょう。

Python:write(ファイルへの書き込み)

Pythonのwriteメソッドは、ファイルオブジェクトに文字列を書き込むために使用されます。このメソッドはopen関数によって返されたファイルオブジェクトで利用できます。

まず最初に、ファイルを書き込みモード('w')で開く必要があります。書き込みモードで開いたファイルに対して、writeメソッドを使用してデータを書き込むことができます。

txt = "ファイルへ書き込む内容"

# ファイルを新規作成
file = open("sample.txt", "w",encoding='utf-8')

# writeメソッドを利用しファイルに文字を書き込む
file.write("Hello Python!")
file.write(txt)

# ファイルを閉じる
file.close()

参考 Python:変数の使い方

結果がこちら↓。

図2:writeメソッドの実行結果

引数に指定した文字列(文字列オブジェクト)をそのままファイルに書き込みます。

注意点として、writeメソッドは自動的に改行('\n')を挿入しません。したがって、改行を含めたい場合は、明示的に文字列の中に改行を追加する必要があります。

txt = "ファイルへ書き込む内容"

# ファイルを新規作成
file = open("sample.txt", "w",encoding='utf-8')

# writeメソッドを利用しファイルに文字を書き込む
file.write("Hello Python!")
file.write("\n"+txt)

# ファイルを閉じる
file.close()

参考 エスケープシーケンス

Python:read(ファイルの読み込み)

readメソッドは、ファイルからデータを読み込むために使用されます。

readメソッドもopen関数によって返されたファイルオブジェクトに対して使用することができます。

ファイルを読み込むためには、まずファイルを読み取りモード('r')で開く必要があります。その後、readメソッドを使用してファイルの内容を読み込むことができます。

txt = "ファイルへ書き込む内容"

# ファイルを新規作成
file = open("sample.txt", "w",encoding='utf-8')

# writeメソッドを利用しファイルに文字を書き込む
file.write("Hello Python!")
file.write("\n"+txt)

# ファイルを閉じる
file.close()

# ファイルを読み取りモードで開く(モードr)
file = open("sample.txt", "r",encoding='utf-8')

# content にファイルの中身を受け渡す
content = file.read()
print(content)

### 実行結果 ###
# Hello Python!
# ファイルへ書き込む内容

readメソッドは引数を指定することで、読み込む文字数を制限することも可能です。たとえば、f.read(10)とすると、ファイルの先頭から10文字だけを読み込みます。また、readメソッドはファイルポインタ(現在の読み込み/書き込み位置)を進めます。したがって、同じreadメソッドを連続して呼び出すと、前回読み込んだ位置の次から読み込みが開始されます。

# ファイルを読み取りモードで開く(モードr)
file = open("sample.txt", "r", encoding='utf-8')

# readメソッドを利用し、最初の10文字だけを読み込む
content = file.read(10)
print(content) # "Hello Pyth" が出力される

# 続けて、次の5文字を読み込む
content = file.read(5)
print(content) # "on!" が出力される

# seekメソッドを使って読み込み位置(ファイルポインタ)をファイルの先頭に移動する
file.seek(0)

# 再び全内容を読み込む
content = file.read()
print(content) # 全内容が再び出力される

# ファイルを閉じる
file.close()

このコードでは、まずread(10)を使って最初の10文字を読み込み、それを出力します。次にread(5)を使って、その次の5文字を読み込みます。

その後、seek(0)を使って読み込み位置(ファイルポインタ)をファイルの先頭に戻し、最後にread()を使ってファイルの全内容を再び読み込みます。

このように、readメソッドとseekメソッドを組み合わせることで、特定の部分だけを読み込む、または特定の位置から読み込むといった操作が可能になります。

Python:close(ファイルを閉じる)

closeメソッドは、open関数によって開かれたファイルを閉じるために使用されます。ファイルを開いた後は、作業が完了したら必ずファイルを閉じることが推奨されています。これは、開かれたファイルがシステムリソースを占有しているためです。

closeメソッドの基本的な使用方法は以下のとおりです。

# ファイルを書き込みモードで開く
file = open('file.txt', 'w')

# 何かしらの操作(ここでは文字列の書き込み)を行う
file.write('Hello, World!')

# ファイルを閉じる
file.close()

ただし、Pythonではwithステートメントを使用すると、ファイルが自動的に閉じられるため、closeメソッドを明示的に呼び出す必要はありません。以下にその例を示します。

# ファイルを書き込みモードで開く
with open('file.txt', 'w') as file:
    # 何かしらの操作(ここでは文字列の書き込み)を行う
    file.write('Hello, World!')
# withブロックを抜けるとファイルは自動的に閉じられる

このwithステートメントを使用した方法は、ファイルを明示的に閉じ忘れることがないため、より安全なコードを書くことができます。このため、通常はwithステートメントを使用してファイル操作を行うことが推奨されています。

実は、ファイル操作を行う場合には基本的にはwith文を利用することが一般的です。
with文の利用方法については以下の記事で解説を行っておりますので、詳しくはこちらの記事をご覧ください。

Python:ファイル操作のまとめ

Python:ファイル操作のまとめ
  • ファイルオープン: open()関数を使い、ファイルを開く
  • モード指定: ファイルを開く際に、読み取り('r')、書き込み('w')、追記('a')などのモードを指定
  • ファイル読み書き: read()write()readlines()writelines()などのメソッドでファイル操作
  • ファイルクローズ: close()メソッドでファイルを閉じる
# ファイル読み取り
with open('example.txt', 'r') as file:
    content = file.read()
print(content)

# ファイル書き込み
with open('example.txt', 'w') as file:
    file.write("Hello, world!")

# ファイル追記
with open('example.txt', 'a') as file:
    file.write("\nGoodbye, world!")

始めてPythonを勉強するのは結構難しいですよね。

でもその悩みを抱えているのは一人じゃありません。全てのPython使いが同じ道を進んできました。

Pythonをはじめとするプログラミングスキルを武器に、時間と場所に捉われない自由な生き方を目指してみませんか?今すぐ行動したい方は以下の記事をチェック!

読者料典 Python入門:学習カリキュラム ←こちらから!

このWebサイトは現役のエンジニアが以下3点を目的として運営しています。

  1. 勉強:一度理解した内容を忘れないように。
    → アウトプットは「最強のインプット」である! 
  2. 備忘:忘れたとしても後から見返せるように。
    → 未来の自分への「お手紙」を書いています。 
  3. 共有:〇〇ってこうだったんだ!の感動をシェアできるように。
    → あなたの知識は誰かにとっての「価値ある情報」です。 

副業ブログの始め方はこちらから

スポンサーリンク
Python
シェアする
ビズドットオンラインをフォローする
タイトルとURLをコピーしました