ユーニックス総合研究所

  • home
  • archives
  • python-append-text-file

Pythonでテキストファイルに追記する

  • 作成日: 2021-04-25
  • 更新日: 2023-12-24
  • カテゴリ: Python

Pythonでテキストファイルに追記する

Pythonではテキストファイルを扱うことができます。
テキストファイルを開いて、内容を読み込んだり逆に内容を書き込んだりすることが可能です。

この記事ではPythonでテキストファイルに追記する方法をわかりやすく解説します。
結論から言うとテキストの追記は↓のようなコードを書きます。

with open('file.txt', 'a') as fout:  
    fout.write('123\n')  

具体的に↓を解説していきます。

  • 追記とはなにか?
  • open()のモード
  • 追記モード a, at
  • 追記モードの仕様
  • テキストファイルに追記する
  • ストリーム位置の検証
  • 追記モードでランダムアクセスを試す

追記とはなにか?

テキストファイルへの追記ですが、この「追記」とは具体的にどういうことを言うのでしょうか?
プログラムにおけるファイルへの追記とは、ファイルの末尾にデータを追加することを言います。

たとえば↓のような内容のテキストファイルがあるとします。

abc  
def  

↑のようなテキストファイルに追記する場合を考えます。
追記したいデータは「123\n」という文字列です。
↑のテキストファイルに「123\n」という文字列を追記した場合、その結果は↓のようになります。

abc  
def  
123  

↑のようにテキストファイルの末尾に文字列を追加して書くのが追記です。
バイナリファイルの場合も同様で、その場合は追記するデータが文字列ではなくバイナリデータになります。

open()のモード

Pythonではテキストファイルを開くときに組み込み関数のopen()を使います。
open()の第1引数には開きたいファイルのパス、第2引数にはファイルの開き方であるモードを指定します。

代表的なモードにはrrt, wwtなどがあります。

open('file.txt', 'r')  
open('file.txt', 'w')  

これらのモードはどれもテキストファイルからの読み込み、またはテキストファイルへの書き込みを実現するモードです。
テキストファイルへ追記したい場合はa, atという専用のモードが用意されています。

追記モード a, at

open()のモードであるaまたはatは、テキストファイルに追記したい時に選択するモードです。
aappend(追記)のaです。ttexttです。
つまりappend textatということになります。

aは暗黙的にテキストファイルを開きます。よってaatは基本的には同じモードです。

open('file.txt', 'a')  
open('file.txt', 'at')  

aまたはatでテキストファイルを開いたとき、開いたファイルオブジェクト(ストリーム)のストリーム位置は末尾に移動している状態になっています。
つまりこの状態からwrite()を呼び出せば、それだけでファイルの末尾にデータを追記できることになります。

追記モードの仕様

ファイルオブジェクト内のストリーム位置を自由に変更することをランダムアクセスといいます。
ランダムアクセスについては↓の記事をご覧ください。

ランダムアクセスではseek()を使ってストリーム位置を自由に変更しますが、追記モード(a, at)の場合はどうなのでしょうか?
seek()を使ってストリーム位置を変更できるのでしょうか?

答えは「ストリーム位置は変更できるが、書き込み位置は変更できない」になります。
a, atモードで開いたファイルオブジェクトのwrite()メソッドは、常にファイル末尾にデータを書き込みます。
これはseek()でストリーム位置をたとえば先頭に持ってきたとしても同じです。
常に書き込み位置はファイル末尾になります。

よって既存のファイルにランダムアクセスしたい場合は、モードr+を使うと良いでしょう。
このモードであればストリーム位置を自由に変更できますし、書き込みも出来ます。

テキストファイルに追記する

↓のようなテキストファイルfile.txtがあるとします。

abc  
def  

このテキストファイルに文字列を追記するには↓のようなコードを書きます。

with open('file.txt', 'a') as fout:  
    fout.write('123\n')  
    fout.write('223\n')  

↑のコードを実行すると、file.txtの中身は↓のようになっています。

abc  
def  
123  
223  

細かく見ていきます。
まずwith文についてです。
with文はopen()で開いたファイルオブジェクトのclose()メソッドを自動的に呼び出します。
よてwith文のブロックが終わると、開いたファイルは自動的にクローズされます。
ファイルの開きっぱなしを予防したい場合はwith文をつけておくと安心できます。

open()の第1引数には開きたいファイルのパス、ここではfile.txtを指定しています。
それからモードにはa, つまりテキストファイルの追記モードを指定しています。

open()で開いたファイルオブジェクトはfoutという変数に保存しています。
foutfile outputの略です。これの逆はfinで、こちらはfile inputの略です。
どちらもUNIX系のプログラミングではよく使われる慣例的な命名です。

ファイルオブジェクトを開いたら、そのメソッドwrite()に文字列を渡して呼び出します。
aまたはatで開いたファイルオブジェクトのwrite()は常にファイル末尾にデータを追記します。

ストリーム位置の検証

追記モードのストリーム位置を検証してみたいと思います。
↓のようなテキストファイルがあるとします。

abc  
def  

このテキストファイルを追記モードで開き、tell()の返り値を表示します。
tell()は現在のストリーム位置を返すメソッドで、その返り値はバイト数になっています。

with open('file.txt', 'a') as fout:  
    print(fout.tell())  

↑の結果は↓になります。

8  

結果は8バイトになりました。
file.txtは改行も含めるとその合計は8バイトになっていますので、ファイルの末尾にストリーム位置が移動しているのがわかります。

追記モードでランダムアクセスを試す

先述のように追記モードのランダムアクセスは意図した動作にはなりません。
具体的に見ていきます。
↓のようなテキストファイルがあるとします。

abc  
def  

このファイルを追記モードで開き、ランダムアクセスでファイルの先頭に文字列を書き込むとします。
その場合のコードは↓のようになります。

import os  

with open('file.txt', 'a') as fout:  
    fout.seek(0, os.SEEK_SET)  # ファイル先頭にストリーム位置を移動  
    print(fout.tell())  # ストリーム位置の確認  
    fout.write('123\n')  # どこに書き込まれる?  

↑の結果は↓になります。

0  

file.txtの中身は↓のように変更されます。

abc  
def  
123  

seek()は第2引数の基点位置を基点に、第1引数のバイト数にストリーム位置を移動するメソッドです。
この場合は基点位置がos.SEEK_SETになっていますので、ファイルの先頭になります。

結果を見ると、なんとストリーム位置は先頭に移動しているのに、書き込みはファイルの末尾に行われました。
これは追記モードの不思議な挙動です。
結果のようにファイルを追記モードで開きwrite()を呼び出すと、その書き込み位置は常にファイル末尾になります。
これは混乱しやすいところだと思います。

おわりに

今回はPythonのテキストファイルの追記方法について見てきました。
ファイルの末尾に書き込みができるようになると、ログの記録などができるようになります。
また、追記モード時のランダムアクセスには気をつけたいところですね。

🦝 < 通帳に0を追記

🐭 < 先頭にマイナスも