HOWTO · Python

Python の出力をファイルにリダイレクトする方法

このチュートリアルでは、Python の出力をファイルにリダイレクトする方法を説明します

このページの内容

Python でテキストをファイルに保存するには、open()でファイルを開き、返されたファイルオブジェクトを使って書き込みます。モード"w"はファイルを新規作成するか既存の内容を置き換え、"a"は末尾に内容を追加します。with文を使うと、ブロックの終了時にファイルが閉じられます。

次の例では、report.txtにメッセージを書き込み、保存した内容を表示します。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "report.txt"
    with path.open("w", encoding="utf-8") as file:
        file.write("Monthly report\nRevenue: 1200\n")
    print(f"Saved to {path.name}:")
    print(path.read_text(encoding="utf-8"), end="")
Saved to report.txt:
Monthly report
Revenue: 1200

以下の例では、write()、print()、標準出力のリダイレクト、writelines()、pathlibのパスインターフェースを使い分ける方法を説明します。ほとんどの例ではwith文によってファイルが自動的に閉じられます。sys.stdoutの例では、元のストリームを復元してからファイルを明示的に閉じます。

open()とwrite()でテキストを書き込む

open()でファイルの開き方を指定し、返されたファイルオブジェクトのメソッドとしてwrite()を呼び出します。モード"w"はファイルを新規作成するか既存の内容を置き換えます。モード"a"は、ファイルがなければ作成し、末尾にテキストを追加します。これらはファイルを開くときのモードであり、write()の操作ではありません。

write()が受け取るのは文字列で、改行は自動的に追加されません。改行したい位置に\nを含めます。戻り値は書き込まれた文字数です。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "notes.txt"
    with path.open("w", encoding="utf-8") as file:
        file.write("First line\n")
        file.write("Second line\n")
    print(path.read_text(encoding="utf-8"), end="")
First line
Second line

末尾に追加するには、モードを"a"にします。たとえば、with open("notes.txt", "a", encoding="utf-8") as file: file.write("Next entry\n")とすると、既存の内容の後に1行追加されます。別のパスを指定しない場合、パスはプログラムの現在の作業ディレクトリを基準に解決されます。

print()でファイルに出力する

print()の使い慣れた書式設定を使いつつ、出力をファイルに保存するには、print(..., file=file_object)を使います。print()はオブジェクトをテキストに変換し、複数の値を既定では空白で区切り、末尾に改行を追加します。sepとendを指定すると、区切り文字や末尾の文字を変更できます。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "summary.txt"
    with path.open("w", encoding="utf-8") as file:
        print("Count:", 3, file=file)
        print("Ready:", True, file=file)
    print(path.read_text(encoding="utf-8"), end="")
Count: 3
Ready: True

withブロックを抜けると、出力が終わったファイルは自動的に閉じられます。そのブロック内でclose()を呼び出す必要はありません。

sys.stdoutで標準出力をリダイレクトする

sys.stdoutは、file引数を指定しない場合にprint()が使うストリームです。ファイルをsys.stdoutに代入すると、プロセスの標準出力がそのファイルにリダイレクトされます。そのため、元のストリームを保存して復元し、ファイルを閉じる必要があります。通常の一時的なリダイレクトには、次の節で説明するcontextlib.redirect_stdout()が便利です。sys.stdoutのリファレンスも参照してください。日本語版の参照先はありません。

import sys
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "log.txt"
    previous_stdout = sys.stdout
    file = path.open("w", encoding="utf-8")
    try:
        sys.stdout = file
        print("Job complete")
    finally:
        sys.stdout = previous_stdout
        file.close()
    print(path.read_text(encoding="utf-8"), end="")
Job complete

finallyで元のストリームを復元しておけば、リダイレクト中の処理が失敗した場合も含め、その後の出力は元の出力先に送られます。外側のwithは一時ディレクトリを管理します。ファイル自体は、sys.stdoutを復元した後に明示的に閉じます。

contextlib.redirect_stdout()で出力を一時的にリダイレクトする

contextlib.redirect_stdout()は、withブロックの中でsys.stdoutをファイルのように扱えるオブジェクトへ一時的に切り替えます。ブロックを抜けると、標準出力は元のストリームに戻ります。ファイルは別途with文で管理します。

import contextlib
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "output.txt"
    with path.open("w", encoding="utf-8") as file:
        with contextlib.redirect_stdout(file):
            print("Build finished")
    print(path.read_text(encoding="utf-8"), end="")
Build finished

この方法では、コンテキスト内で呼び出したprint()や、標準出力へのその他の書き込みを取り込めます。標準エラー出力(sys.stderr)はリダイレクトされません。

writelines()で文字列の並びを書き込む

writelines()は、イテラブルに含まれる各文字列を順番にファイルへ書き込みます。改行は挿入されないため、ファイル内で行を分けたい場合は文字列に\nを含めます。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "items.txt"
    lines = ["apples\n", "pears\n", "plums\n"]
    with path.open("w", encoding="utf-8") as file:
        file.writelines(lines)
    print(path.read_text(encoding="utf-8"), end="")
apples
pears
plums

テキストファイルに書き込む要素は文字列である必要があります。改行が不要であれば、各文字列に\nを含めないでください。

pathlibでファイルを開いて書き込む

pathlibは、ファイルシステムのパスを組み立てたり操作したりするためのオブジェクトを提供します。ファイルオブジェクトの代わりになるものではありません。Path.open()でファイルオブジェクトを取得し、そのwrite()メソッドを呼び出します。フォルダー名など複数の要素からパスを組み立てる場合に便利です。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "archive" / "entry.txt"
    path.parent.mkdir()
    with path.open("w", encoding="utf-8") as file:
        file.write("Stored with pathlib.\n")
    print(path.read_text(encoding="utf-8"), end="")
Stored with pathlib.

ファイルオブジェクトを直接管理せず、テキストを書き込む処理を簡潔に済ませたい場合は、Path.write_text()を使えます。繰り返し書き込む場合やwritelines()などのメソッドを使う場合は、Path.open()でファイルオブジェクトを取得します。

逆にファイルを読み込む方法については、Python でファイルを文字列に読み込む方法を参照してください。