連載
» 2021年04月16日 05時00分 公開

[解決!Python]テキストファイルに書き込むには解決!Python

open関数でファイルを書き込み用にオープンし、ファイルに文字列を書き込む方法や書き込みのモード、pathlib.Pathクラスを使う方法などを紹介する。

[かわさきしんじ,Deep Insider編集部]
「解決!Python」のインデックス

連載目次

# ファイルを書き込み用にオープンして、ファイル先頭から文字列を書き込む
with open('test.txt', 'w') as f:  # 「with open('test.txt', 'wt') as f:」と同じ
    f.write('this is a test.\n'# 改行したければ改行文字を最後に付加
    sl = ['atmark IT\n', 'deep insider\n']
    f.writelines(sl)  # 文字列リストはwritelinesメソッドで書き込む
    x = 1
    f.write(str(x) + '\n'# テキストファイルに書き込めるのは文字列のみ

# 上で作成した内容の確認
from pathlib import Path

print(Path('test.txt').read_text(), end='')
# 出力結果:
#this is a test.
#atmark IT
#deep insider
#1

# with文を使わない場合
f = open('test.txt', 'w')
f.write('this is a test.\n'# 戻り値は書き込んだ文字数
f.close()

# pathlibモジュールのPathクラスが提供するwrite_textメソッドを使用
p = Path('test.txt')
p.write_text('foo\nbar\nbaz\n')

print(p.read_text(), end='')
# 出力結果:
#foo
#bar
#baz

# ファイルを追記
with open('test.txt', 'a') as f:
    f.write('deep insider\n')

print(Path('test.txt').read_text(), end='')
# 出力結果:
#foo
#bar
#baz
#deep insider

# ファイルを排他的に作成してオープン
with open('test.txt', 'x') as f:  # 既に存在しているのでFileExistsError例外
    pass

with open('test2.txt', 'x') as f:
    f.write('absolutely a new line!\n')

print(Path('test2.txt').read_text(), end=''# absolutely a new line!


テキストファイルに書き込む基本

 テキストファイルに書き込みを行う基本的な流れを以下に示す。

  1. テキストファイルを書き込み用にオープンする(open関数)
  2. open関数で取得したファイルオブジェクトを介して書き込みを行う(write/writelinesメソッド)
  3. テキストファイルをクローズする(closeメソッド)

 open関数の構文を以下に示す。以下の構文で省略されているパラメーターについては、Pythonのドキュメント「open()」を参照されたい。

open(file, mode)


 引数fileには書き込みを行う対象となるテキストファイルのファイル名を指定する。文字列でカレントディレクトリからの相対パスもしくは絶対パスでファイル名を指定するのが一般的だが、Pythonのpathlib.Pathオブジェクト(path-like object)を渡してもよい(Pathオブジェクトをopen関数に渡す例については、読み込み目的のオープンについての話ではあるが、「[解決!Python]テキストファイルを読み込むには」を参照のこと)。

 引数modeには以下のいずれかを指定する。

  • 'w': 書き込み用にオープンする。既存のファイルをオープンしたときには、以前の内容は削除され、ファイルの先頭から新たに書き込みが行われる
  • 'a': 書き込み用にオープンする。既存のファイルをオープンしたときには、以前の内容の末尾に追加で書き込みが行われる
  • 'x': 書き込み用にファイルをゼロから新規に作成してオープンする。既存のファイルをオープンしようとしたときには、FileExistError例外を発生させる

 テキストファイルをオープンすることを意味する't'を上記に付加してもよい('wt'など)。ただし、これは省略可能である(バイナリファイルをオープンするときの'b'指定は必須)。

 以下に「open関数」→「ファイルへの書き込み」→「ファイルのクローズ」という大まかな流れを示す。

f = open('test.txt', 'w')
f.write('this is a test.\n'# 戻り値は書き込んだ文字数
f.close()


 ただし、ファイルへの書き込み時には、プログラム内外の現象を要因として例外が発生して、(外処理をきちんとしていないと)ファイルをクローズする前にプログラムが終了してしまうこともある。特にファイル書き込み時にこうなると、ファイルに保存したはずのデータが保存されていないといったことも起こるかもしれない。そのため、with文を使って、with文のブロックの終了時やブロック内での例外発生時に必ずファイルがクローズされるようにすることをおすすめする。

with open('test.txt', 'w') as f:
    # ファイルへの書き込みを行う
    pass


 open関数の戻り値は、書き込み対象のファイルを表すファイルオブジェクトであり、このオブジェクトを介してファイルに書き込みを行う。

 なお、本稿では、書き込んだファイルの内容を確認するのに、pathlibモジュールのPathクラスが持つread_textメソッドを使用する(print関数の引数endに空文字列を指定しているのは、本稿の例では基本的に、改行文字付きでファイルに文字列を出力しているので、最後に余計な改行を表示しないようにするため)。

from pathlib import Path

print(Path('test.txt').read_text(), end='')


ファイルを書き込み用にオープンして、ファイル先頭から文字列を書き込む

 ファイルを書き込み用にオープンし、(既存のファイルであれば、以前の内容を空にして)ファイル先頭から文字列を書き込むには、先ほども述べたようにopen関数の引数modeに'w'(もしくは'wt')を指定して、ファイルをオープンすればよい。ファイルオブジェクトを得たら、writeメソッドやwritelinesメソッドを使って書き込みを行う。

 以下に例を示す。

with open('test.txt', 'w') as f:
    f.write('atmark IT\n')

print(Path('test.txt').read_text(), end='')
# 出力結果:
#atmark IT


 この例では、writeメソッドでファイルに書き込みを行っている。writeメソッドは文字列を引数として受け取り、ファイルに出力する。その戻り値は書き込みを行った文字数となる。上の例を見ると分かるが、writeメソッドにより自動で改行文字が追加されるようなことはないので、必要なところで自分で改行文字を追加する必要がある。

 複数の文字列をファイルに書き込むにはwritelinesメソッドを使用する。

sl = ['atmark IT', 'deep insider']
with open('test.txt', 'w') as f:
    f.writelines([w + '\n' for w in sl])  # 末尾に改行文字を追加して書き込み

print(Path('test.txt').read_text(), end='')
# 出力結果:
#atmark IT
#deep insider


 この例では、2つの文字列を要素とするリストの内容をファイルに書き込んでいるが、元の文字列リストには改行文字が付加されていないので、リスト内包表記を使って各要素の末尾に改行文字を追加している。

 テキストファイルへの書き込みで重要なのは、テキストファイルには文字列型の値しか書き込めないことだ。以下の例では、整数値「1」をテキストファイルに書き込もうとしているが、これは文字列ではないのでTypeError例外が発生する。これらは何らかのロジックに従って文字列化してから書き込む必要がある(以下の2つ目の例では単純にstr関数で文字列化している)。

x = 1
with open('test.txt', 'w') as f:
    f.write(x)  # TypeError例外

with open('test.txt', 'w') as f:
    f.write(str(x) + '\n'# 文字列に変換して書き込み


 そうではなく、「1」というデータそのものをファイルに書き込みたいのであれば、バイナリファイルを使う必要がある(これについては別稿で取り上げる予定だ)。

 なお、Pythonのpathlibモジュールが提供するPathクラスにはwrite_textというインスタンスメソッドがある。これを使うと、ファイルのオープン/書き込み/クローズという処理をまとめて実行できるので、覚えておくとよいかもしれない。

p = Path('test.txt')
p.write_text('foo\nbar\nbaz\n')

print(p.read_text(), end='')
# 出力結果:
#foo
#bar
#baz


 write_textメソッドが受け取るのは文字列のみで、文字列以外の値(文字列リストや整数値など)を指定すると例外となる。よって、これはファイルをオープンして、writeメソッドで書き込んで、クローズするという処理に相当するものと考えておこう。複数の文字列を書き込みたければ、以下のように改行文字を区切り文字として、文字列リストの要素を1個の文字列に連結する。

sl = ['atmark IT', 'deep insider']
s = '\n'.join(sl)
p = Path('test.txt')
p.write_text(s)

print(p.read_text())


 write_textメソッドを既存のファイルに対して呼び出した場合には、以前の内容は上書きされる。そのため、ファイルへの追記などの目的でこれを使用することはできない。

テキストファイルに追記

 テキストファイルに追記するときには、open関数の引数modeに'a'(または'at')を指定して、ファイルをオープンする。その後の書き込みは上と同様、writeメソッドやwritelinesメソッドを使用する。

 以下に例を示す。

Path('test.txt').write_text('atmark IT\n'# test.txtファイルに1行書き込み
print(Path('test.txt').read_text(), end='')
# 出力結果:
#atmark IT

with open('test.txt', 'a') as f:  # 追記用にオープン
    f.write('deep insider\n')

print(Path('test.txt').read_text(), end='')
# 出力結果:
#atmark IT
#deep insider


 この例では、最初にPathクラスのインスタンスに対してwrite_textメソッドを呼び出して、ファイルに書き込みを行った後、引数modeに'a'を指定して同じファイルをオープンし、そこに書き込みを行っている。writeメソッドで書き込んだ内容が、追記されていることに注目しよう。

ファイルを排他的に作成して、書き込み用にオープン

 open関数の引数modeに'x'を指定した場合には、ファイルを排他的に作成して、書き込み用にオープンすることを意味する。ここでいう「排他的」とは、ファイルを作成する場所に、そのファイルが存在していないということだ(それまでに存在しなかったものを独占的に作成する、といった意味)。そのため、引数modeに'x'を指定して、既存のファイルをオープンしようとすると、FileExistsError例外が発生する。

 以下に例を示す。

with open('test.txt', 'x') as f:  # 既に存在しているのでFileExistsError例外
    pass

with open('test2.txt') as f:  # 存在しないのでFileNotFoundError例外
    pass

with open('test2.txt', 'x') as f:  # 上で存在していなかったのでOK
    f.write('absolutely a new file!\n')

print(Path('test2.txt').read_text(), end=''# absolutely a new file!


「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。