MENU

CSVの途中ファイルを分ける|Pythonの一時保存

当ページのリンクには広告(PR)が含まれていることがあります。
CSVの途中ファイルを分ける|Pythonの一時保存。集計中のCSV、一時ファイルへ、完成後に置換の処理例。

CSVを正式な名前へ直接書き続けると、処理の途中に別の担当者が不完全なファイルを読むことがあります。途中で失敗した場合も、正式名のまま中途半端な内容が残る構成になります。

一時ファイルへ最後まで書き、読み戻して条件を確認した後に、正式な名前へ置き換える方法があります。完成前の出力を正式名へ公開しないことが目的です。

目次

検査後だけ正式ファイルへ置き換える

次は一時フォルダー内に、練習用の旧CSVを作って試します。利用者のファイルは対象にしません。同じ親フォルダーへ一時出力し、行数と金額を検査してからos.replaceを呼びます。

import csv
import os
from pathlib import Path
from tempfile import NamedTemporaryFile, TemporaryDirectory

def save_report(target, rows):
    staged = None
    try:
        with NamedTemporaryFile(
            mode="w", encoding="utf-8-sig", newline="",
            dir=target.parent, prefix=".part-", suffix=".csv", delete=False
        ) as output:
            staged = Path(output.name)
            writer = csv.DictWriter(output, fieldnames=["ID", "金額"])
            writer.writeheader()
            writer.writerows(rows)
        with staged.open(encoding="utf-8-sig", newline="") as source:
            saved = list(csv.DictReader(source))
        if len(saved) != len(rows) or any(not row["ID"] for row in saved):
            raise ValueError("件数かIDを確認してください")
        for row in saved:
            int(row["金額"])
        os.replace(staged, target)
    finally:
        if staged is not None:
            staged.unlink(missing_ok=True)

with TemporaryDirectory() as directory:
    target = Path(directory) / "report.csv"
    original = "ID,金額\nOLD,50\n"
    target.write_text(original, encoding="utf-8")
    try:
        save_report(target, [{"ID": "A", "金額": "不明"}])
    except ValueError:
        pass
    same = target.read_text(encoding="utf-8") == original
    print("失敗時に旧ファイルを維持:", same)
    assert same
    save_report(target, [{"ID": "A", "金額": 100}])
    with target.open(encoding="utf-8-sig", newline="") as source:
        result = list(csv.DictReader(source))
    print("成功時の金額:", result[0]["金額"])
    assert result == [{"ID": "A", "金額": "100"}]

金額が不明の入力では旧ファイルが残り、正常な入力では100のCSVへ替わります。Windows・Python 3.12.10で、この二つの結果を確認しました。練習用の一時ファイルは処理後に片付けられます。

一時ファイルを閉じてから操作する

NamedTemporaryFileを使うと、重複しにくい一時名を作れます。例はwithを抜けて書き込み口を閉じてから、読み戻しと置き換えを行います。

正式先と同じ親フォルダーへ作っているのは、別のファイルシステム間の移動を避けるためです。保存先の権限や、ほかのアプリがファイルを開いている状態などで、置き換えが失敗する可能性は残ります。

バックアップと同時実行は別に必要

os.replaceは既存の正式ファイルを置き換えます。誤った完成データを検査で見逃した場合、旧内容へ戻すための控えは別に必要です。一時保存そのものを履歴の保管と考えないようにします。

二つの処理が同時に同じ正式名を更新する競合も、このコードでは止めていません。実行を一つにする仕組みや、対象入力と結果を対応させる記録を別に用意します。電源断時の復旧や共有フォルダー上の動作まで、一律に保証する例でもありません。

実運用へ進める前に、検査失敗、書き込み権限不足、置き換え失敗のときに、旧ファイルと一時ファイルがどう残るかを、コピーした作業場所で確かめてください。

読み書きの基本はPythonのファイル操作、戻すための控えはバックアップ設計で確認できます。

参考資料

os、tempfile、csvの公式資料を2026年11月1日に確認しました。

この記事を書いた人

Watanabeのアバター Watanabe サイト運営者

2020年よりブログ開始。
SEOが思いのほか性にあっていたようで現在に至る。
モットーは「勝率の高い選択をする」
AIは活用するが吉、最後は人間が息を吹き込む。
アートと科学を追求し、日々精進。
―――
収益:6~7桁をウゴウゴ。
サイト:ペラサイト~中規模サイトまで運営中。
案件:1000円以上の案件をメインに取組中。
打ち手:ブラックSEO~ホワイトSEOまで
―――

目次