Pythonでテキストファイルを書き込むことは、ログを保存したり、レポートを自動生成したり、ちょっとしたメモを残すときにも役立つ、とても実用的なスキルです。
本記事ではwriteとprintの2つの方法を比較しながら、テキストファイル書き込みの基本から応用例までを体系的に解説します。
実際に動かせるサンプルコードを豊富に掲載しているので、手を動かしながら理解していきましょう。
Pythonでテキストファイルを書き込む基本
Pythonでテキストファイルを書き込む流れ

テキストファイルを書き込む基本的な流れは、とてもシンプルです。
どの方法でも、次の3ステップを踏みます。
1つ目はファイルを開くことです。
Pythonのopen関数を使い、ファイル名やモード(書き込みか追記かなど)、文字コードを指定します。
2つ目はデータを書き込むことです。
ファイルオブジェクトに対してwriteメソッドを呼び出すか、print関数にfile引数を渡して書き込みます。
3つ目はファイルを閉じることです。
通常はcloseメソッドを呼びますが、実務ではwith文を使って自動で閉じる書き方がよく使われます。
まずは最もシンプルな例を見てみましょう。
# 基本的なテキストファイル書き込みの例
# ファイルを開く (書き込みモード, UTF-8)
f = open("example.txt", mode="w", encoding="utf-8")
# 文字列を書き込む
f.write("こんにちは、Pythonのテキスト書き込み!")
# ファイルを閉じる
f.close()
このコードを実行すると、カレントディレクトリ(スクリプトを実行した場所)にexample.txtというファイルが作成され、その中に1行のテキストが保存されます。
ファイルモード(w,a,x)の違い

ファイルモードは、ファイルをどのように扱うかを決める重要な指定です。
とくによく使うのが"w"、"a"、"x"の3つです。
それぞれの挙動を、表で整理しておきます。
| モード | 意味 | 既存ファイルがある場合 | ない場合 |
|---|---|---|---|
| w | 書き込み(上書き) | 中身を消して書き直す | 新規作成して書き込む |
| a | 追記(append) | 末尾に追記する | 新規作成して書き込む |
| x | 新規作成専用(write) | 例外(FileExistsError) | 新規作成して書き込む |
既存ファイルの中身を消したくない場合に"w"を使ってしまうと、取り返しがつかないことがあります。
そのようなときは"a"または"x"を検討しましょう。
簡単な実験コードを示します。
# ファイルモードの違いを確認するサンプル
# 1回目: wモードで書き込み (ファイルがなければ作成)
with open("mode_sample.txt", mode="w", encoding="utf-8") as f:
f.write("1回目: wモードで書いた行です。\n")
# 2回目: aモードで追記
with open("mode_sample.txt", mode="a", encoding="utf-8") as f:
f.write("2回目: aモードで追記した行です。\n")
# 3回目: xモード (既にファイルがあるためエラーになります)
try:
with open("mode_sample.txt", mode="x", encoding="utf-8") as f:
f.write("3回目: xモードで書いた行です。\n")
except FileExistsError:
print("xモード: 既にファイルがあるため、FileExistsErrorになりました。")
xモード: 既にファイルがあるため、FileExistsErrorになりました。
このように"x"モードは「上書きしたくない」「絶対に新規ファイルだけに書きたい」という要求に向いています。
文字コード(encoding)の指定と注意点

日本語を含むテキストファイルを書き込むときに必ず意識したいのが文字コード(encoding)です。
Pythonのopen関数ではencoding引数で文字コードを指定できます。
現在の標準的な選択肢は"utf-8"です。
特別な理由がない限り、基本的にはUTF-8を指定しておけば問題ありません。
# UTF-8で日本語を含むテキストファイルを書き込む例
with open("encoding_sample_utf8.txt", mode="w", encoding="utf-8") as f:
f.write("UTF-8で保存した日本語のテキストです。\n")
Windowsの一部アプリケーション(古いメモ帳など)との互換性のために、"cp932"(実質的にShift_JIS系)が必要になる場面もあります。
その場合は次のように指定します。
# Windows向けにcp932(Shift_JIS系)で保存する例
with open("encoding_sample_cp932.txt", mode="w", encoding="cp932") as f:
f.write("cp932(Shift_JIS系)で保存した日本語のテキストです。\n")
異なるencodingでファイルを開くと文字化けが発生するため、どのencodingで保存したかは、プロジェクト全体で統一しておくことがとても重要です。
writeでテキストファイルに書き込む方法
file.writeの基本構文と戻り値

file.writeは、テキストファイル書き込みの最も基本的なメソッドです。
構文は次のようになります。
# writeメソッドの基本構文と戻り値の確認
text = "Hello"
with open("write_basic.txt", mode="w", encoding="utf-8") as f:
# 文字列を書き込む
written = f.write(text)
# writeの戻り値は「書き込んだ文字数」
print("書き込んだ文字数:", written)
書き込んだ文字数: 5
writeは渡した文字列をそのまま書き込み、書き込んだ「文字数」を整数で返します。
この戻り値は、ロギングや検証の目的で使えることがありますが、日常的なスクリプトでは省略されることも多いです。
なお、writeは自動で改行を付けません。
必要な場合は、次の節で説明するように"\n"を含める必要があります。
改行付きで書くには\nを使う

改行を入れながら複数の行を書きたい場合は、文字列中に"\n"を挟みます。
Pythonにおける改行は基本的に"\n"と考えて差し支えありません(Windowsでも同様です)。
# 改行を含めて書き込む例
with open("write_newline.txt", mode="w", encoding="utf-8") as f:
f.write("1行目のテキスト\n")
f.write("2行目のテキスト\n")
f.write("3行目のテキスト\n")
これを開くと、次のような内容になります。
1行目のテキスト
2行目のテキスト
3行目のテキスト
改行を忘れると、すべての内容が1行にくっついてしまうので注意が必要です。
ループの中で行を出力するときは、f.write(line + "\n")のように、毎回改行を追加するのが定番のパターンです。
複数行を書き込むwritelinesの使い方

複数行をまとめて書き込みたいときにはwritelinesメソッドが使えます。
リストやタプルなどの「文字列のイテラブル」を受け取り、その順に連結して書き込みます。
# writelinesで複数行を書き込む例
lines = [
"1行目のテキスト\n",
"2行目のテキスト\n",
"3行目のテキスト\n",
]
with open("writelines_sample.txt", mode="w", encoding="utf-8") as f:
# リスト内の文字列を順番に書き込む (改行は自分で含めておく)
f.writelines(lines)
ポイントはwritelinesは自動で改行を入れないという点です。
改行が必要な場合は、上の例のように各要素に"\n"を付けておきます。
大きなデータを生成する場合、次のように内包表記と組み合わせるとスッキリ書けます。
# 1〜100までの数字を1行ずつファイルに書き込む例
with open("numbers.txt", mode="w", encoding="utf-8") as f:
f.writelines(f"{i}\n" for i in range(1, 101))
上書きと追記の実例

"w"モードと"a"モードの違いを、実際のファイル内容で確認してみましょう。
# 上書き(w)と追記(a)の挙動を確認するサンプル
# 1回目: wモードで上書き(実際には新規作成)
with open("overwrite_append.txt", mode="w", encoding="utf-8") as f:
f.write("1回目: wモードで書いた行です。\n")
# 2回目: wモードで再び開く (前回の内容は消える)
with open("overwrite_append.txt", mode="w", encoding="utf-8") as f:
f.write("2回目: wモードで書いた行です。(1回目は消えます)\n")
# 3回目: aモードで開く (2回目の内容の下に追加される)
with open("overwrite_append.txt", mode="a", encoding="utf-8") as f:
f.write("3回目: aモードで追記した行です。\n")
最終的なoverwrite_append.txtの内容は次のようになります。
2回目: wモードで書いた行です。(1回目は消えます)
3回目: aモードで追記した行です。
このように、同じファイル名でもモードの違いで挙動が大きく変わるため、ログなのか、一時ファイルなのか、レポートなのかといった用途に応じて、適切なモードを選ぶことが大切です。
printでテキストファイルに書き込む方法
print関数でfile引数を指定する書き込み

print関数は通常、標準出力(コンソール)に文字列を表示しますが、file引数にファイルオブジェクトを渡すことで、その出力先をファイルに変更できます。
# print関数を使ってファイルに書き込む例
with open("print_basic.txt", mode="w", encoding="utf-8") as f:
print("こんにちは、printでファイルに書き込みます。", file=f)
print("2行目もprintで書き込みます。", file=f)
このとき、printは自動的に末尾に改行(\n)を付けます。
そのため、1行ずつ出力したいときには非常に便利です。
endとsepで出力フォーマットを調整する

printにはsepとendという2つの便利なキーワード引数があります。
これらを調整することで、CSV形式のような区切り付きテキストや、改行を制御したログを簡単に出力できます。
# sepとendを使ったフォーマット調整の例
with open("print_format.txt", mode="w", encoding="utf-8") as f:
# デフォルト: sep=" ", end="\n"
print("A", "B", "C", file=f) # → "A B C\n"
# カンマ区切りで出力
print("A", "B", "C", sep=",", file=f) # → "A,B,C\n"
# 改行なしで出力 (endを空文字にする)
print("行の途中まで出力...", end="", file=f)
print("ここで改行します。", file=f)
sepは「引数同士の区切り文字」、endは「行の終わりに付ける文字」だと理解しておくと、出力フォーマットを自在にコントロールできます。
標準出力とファイル出力を切り替える方法

標準出力とファイル出力を簡単に切り替えたい場合、出力先を引数で受け取る関数を定義するのが便利です。
こうしておくと、テスト時はコンソール出力、本番ではファイル出力といった切り替えが容易になります。
import sys
def report(message, file=sys.stdout):
"""メッセージを指定された出力先に表示する簡易関数"""
print(message, file=file)
# コンソールに出力
report("これは標準出力(コンソール)へのメッセージです。")
# ファイルに出力
with open("report_log.txt", mode="w", encoding="utf-8") as f:
report("これはファイルへのメッセージです。", file=f)
これは標準出力(コンソール)へのメッセージです。
また、一時的にsys.stdoutを差し替えるテクニックもありますが、コードが分かりづらくなることもあるため、関数引数で切り替えるパターンの方が読みやすいことが多いです。
writeとの違い

writeとprintの違いを整理しておきます。
| 項目 | write | |
|---|---|---|
| 呼び出し方 | f.write(“文字列”) | print(“文字列”, file=f) |
| 改行の自動付与 | しない | デフォルトでend="\n" |
| 戻り値 | 書き込んだ文字数(int) | なし(None) |
| 複数引数の扱い | 不可(自分で連結が必要) | sepで区切って結合 |
| 主な用途 | 厳密なフォーマット、バイナリ | ログ、メッセージ、行単位出力 |
行単位のログ出力やメッセージ出力にはprint、改行位置を自分で制御したい場合やバイナリに近い扱いをしたいときにはwriteと考えると、使い分けやすくなります。
writeとprintの違いと実例集
writeとprintの使い分けポイント

実務上の観点から、writeとprintの使い分けをまとめると次のようになります。
文章やログを「1行=1メッセージ」のように扱い、とにかく行単位で見やすく出したいときはprintを選ぶと楽です。
改行が自動で入り、複数の値もsepで簡単に区切れます。
一方で、改行やスペースの位置を厳密に制御したい場合や、設定ファイルやプロトコル定義などフォーマットが厳格なテキストを書きたいときには、writeの方が適しています。
戻り値の文字数が必要なケースでもwriteを使います。
次の節から、具体的な実例でこの違いを確認していきます。
ログファイル出力の実例

ログファイルの出力はprintの得意分野です。
1行ごとにメッセージを書き、あとからテキストエディタで閲覧しやすくすることが目的だからです。
import datetime
def log(message, file):
"""タイムスタンプ付きでログを1行出力する簡易関数"""
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# [時刻] メッセージ という形式で出力
print(f"[{now}] {message}", file=file)
# ログファイルに追記していく例
with open("app.log", mode="a", encoding="utf-8") as f:
log("アプリケーションを起動しました。", file=f)
log("ユーザーがログインしました。", file=f)
log("処理が完了しました。", file=f)
生成されるapp.logのイメージは次のようになります。
[2025-12-19 10:15:01] アプリケーションを起動しました。
[2025-12-19 10:15:05] ユーザーがログインしました。
[2025-12-19 10:15:10] 処理が完了しました。
このようにログは基本的に「追記(aモード)+print」の組み合わせで実装すると、シンプルで読みやすいものになります。
設定ファイルやレポート出力の実例

設定ファイルやレポートのようにフォーマットに意味があるテキストでは、writeで1行ずつ丁寧に構築するパターンがよく使われます。
まず、シンプルなINI風の設定ファイルを書き出す例です。
# INI風設定ファイルを書き出す例
config = {
"database": {
"host": "localhost",
"port": 5432,
},
"auth": {
"user": "admin",
"password": "secret",
},
}
with open("config.ini", mode="w", encoding="utf-8") as f:
for section, params in config.items():
# セクション行 [section]
f.write(f"[{section}]\n")
# key=value 形式で出力
for key, value in params.items():
f.write(f"{key}={value}\n")
# セクション間に空行
f.write("\n")
生成されるconfig.iniは次のようになります。
[database]
host=localhost
port=5432
[auth]
user=admin
password=secret
次に、簡単なレポートファイルを出力する例です。
ここでは、表形式のヘッダや罫線をwriteで細かく制御しています。
# 簡単なレポートファイルを書き出す例
data = [
("Alice", 90),
("Bob", 75),
("Charlie", 82),
]
with open("report.txt", mode="w", encoding="utf-8") as f:
f.write("成績レポート\n")
f.write("====================\n")
f.write("名前 点数\n")
f.write("--------------------\n")
for name, score in data:
# 名前を左寄せ8文字、点数を右寄せ3桁で整形
line = f"{name:<8} {score:>3}\n"
f.write(line)
f.write("--------------------\n")
avg = sum(score for _, score in data) / len(data)
f.write(f"平均 {avg:>5.1f}\n")
成績レポート
====================
名前 点数
--------------------
Alice 90
Bob 75
Charlie 82
--------------------
平均 82.3
このようにレイアウトをきっちり整えたいテキストはwriteで組み立てると、意図通りのフォーマットを実現しやすくなります。
with文で安全にテキストファイルを書き込むパターン集

ファイル操作ではwith文を使うのがベストプラクティスです。
with文を使うと、ブロックを抜けたタイミングで自動的にcloseが呼ばれ、例外が発生した場合でもファイルがきちんと閉じられます。
ここでは、よく使うパターンをいくつかまとめて紹介します。
単純な上書き書き込みパターン
# 単純にテキストファイルを書き換えるパターン
def save_text(path, text):
"""指定したパスにテキストをUTF-8で保存する関数"""
with open(path, mode="w", encoding="utf-8") as f:
f.write(text)
# 使用例
save_text("simple.txt", "シンプルなテキスト保存の例です。\n")
追記ログパターン(print利用)
# 追記モードでログを書き込むパターン
def append_log(path, message):
"""指定したパスのログファイルに1行追記する関数"""
with open(path, mode="a", encoding="utf-8") as f:
print(message, file=f)
# 使用例
append_log("event.log", "ユーザーがボタンをクリックしました。")
append_log("event.log", "ウィンドウを閉じました。")
一時ファイルを経由した安全な上書きパターン
既存ファイルを安全に書き換えたい場合、一時ファイルに書き込んでからリネームするパターンが有効です。
途中でエラーが起きても、元のファイルが壊れにくくなります。
import os
import tempfile
def safe_overwrite(path, text, encoding="utf-8"):
"""一時ファイルを使って安全に上書き保存する例"""
dir_name = os.path.dirname(path) or "."
# 一時ファイルを同じディレクトリに作成
fd, temp_path = tempfile.mkstemp(dir=dir_name)
os.close(fd) # 低レベルファイルディスクリプタを閉じる
try:
# 一時ファイルに書き込む
with open(temp_path, mode="w", encoding=encoding) as f:
f.write(text)
# 書き込みに成功したら、上書きリネーム
os.replace(temp_path, path)
except Exception:
# 失敗した場合は一時ファイルを削除しておく
if os.path.exists(temp_path):
os.remove(temp_path)
# エラーを呼び出し元に伝える
raise
# 使用例
safe_overwrite("important_config.txt", "重要な設定内容を安全に保存します。\n")
このようなパターンをテンプレートとして覚えておくと、信頼性の高いファイル書き込み処理を簡単に再利用できるようになります。
まとめ
テキストファイルの書き込みは、Pythonプログラミングにおいて頻繁に登場する基本テクニックです。
本記事ではopenのモード(w/a/x)とencoding、writeとprintの使い分け、そして実務で使えるログ出力・設定ファイル・レポート生成のパターンを、サンプルコードとともに解説しました。
改行や文字コードの扱い、with文による安全なクローズを意識すれば、ファイル入出力のトラブルは大幅に減らせます。
ここで紹介したパターンを自分のプロジェクトに取り入れ、テキストファイル出力を自在に扱えるようになってください。
