エラー時の切り分けとバックアップ|PC・ブラウザ・ファイルの基本

このページはプロモーション(広告)を含みます。

PC・ブラウザ・ファイルの基本(初級・読む25分+演習35分)

この授業のゴール

仕事でどう使うか

エラーに出会わない人はいません。仕事で差がつくのは、エラーが出たときに、闇雲に操作せず、原因を絞り込めるかです。そしてもう1つが、失敗しても元に戻せる状態を、あらかじめ作っておくことです。

路線 この授業の使いどころ
DS(データサイエンティスト) 「ファイルが読めない」「列がない」に出会ったとき、エラー文から原因を特定する。分析の途中結果を日付付きで残し、やり直しの時間を減らす
ML(機械学習エンジニア) 学習が途中で止まったとき、データ・コード・環境のどこの問題かを切り分ける。モデルと設定のファイルをバックアップして実験を再現する
DX(DX推進・AI企画) 現場から来た「動かない」という報告から、再現手順と環境情報を聞き出す。バックアップの頻度と保管場所を運用ルールに書く
RS(研究者) 実験データの紛失は研究の失敗になる。原本のコピーを別の場所に持ち、同一性を確認できる状態にする

この授業で、ON01の統合演習(CSVを読み込み、行を確認し、ノートと結果を出力して再読込する)を行います。

前提

前提は、画面とブラウザの役割(層の区別)、ファイル・フォルダ・拡張子(原本を残す)、保存・ダウンロード・アップロード(保存先と上書き)、文字コードと安全なファイル確認(文字コードの確認)です。診断を省略して始めた場合は、各授業の「失敗」の節だけ読み返してから進めても構いません。

復元(バックアップから元に戻す手順)の詳しい説明は、この授業の最後の任意の節にまとめました。

身近な状況:「動きません」と言われたとき

Gさんは、同僚から「CSVが読めません」と連絡を受けました。Gさんは、最初の対応を3つ思いつきました。

  1. パソコンを再起動してもらう
  2. ファイルをもう一度ダウンロードしてもらう
  3. エラーの文を読んでもらう

3つ目が最も早い方法です。エラーの文には、何が・どこで・どう悪かったかの手がかりが入っています。ところが、慌てると読まずに操作を繰り返し、元のファイルを上書きして状況を悪化させがちです。

エラーの切り分けとは、原因の候補を、層ごとに1つずつ消していく作業です。画面とブラウザの役割 で学んだ層(PC・OS・ブラウザ・アプリ・データ)に、ファイルの層(名前・場所・形式・文字コード・中身)を足して考えます。

症状(エラー名) まず疑う原因 確認すること
FileNotFoundError 名前・場所・作業フォルダ スペル、拡張子、フォルダ、相対か絶対か
UnicodeDecodeError 文字コード UTF-8かCP932か、BOM
KeyError 列名 大文字小文字、空白、全角半角、BOM
ValueError 値の形 カンマ、空白、全角数字、欠損
PermissionError 権限・使用中 他のアプリで開いていないか、保存先

直感的な説明:問診と、1か所だけ変える原則

切り分けは、医者の問診に似ています。

特に大事なのは、1度に変えるのは1か所という原則です。ファイル名とフォルダと文字コードを同時に変えて動いたとしても、何が原因だったのか分かりません。次に同じことが起きたとき、また同じ苦労をします。

バックアップは、問診の前に取る保険です。切り分けの途中でファイルを壊しても、元に戻せるなら、思い切って試せます。

たとえの限界:人体と違い、データは完全に複製できます。複製が元と同じかどうかも、ハッシュ値で確かめられる点が、データならではの強みです。

正確な定義:切り分けの手順、ハッシュ、3-2-1の考え方

切り分けの5手順

  1. エラー文を全部読む:例外の名前、メッセージ、最後に出た行を書き写す。
  2. 再現手順を書く:同じエラーを、もう一度起こせる最短の手順にする。
  3. 層を決める:名前・場所・形式・文字コード・列名・値の、どれかに当てはめる。
  4. 1か所だけ変えて再実行:結果をメモする。
  5. 記録する:原因と直し方を1行残す。

エラー文は、例外の名前とメッセージでできています。実際に確かめましょう。

import pandas as pd

def attempt(label, fn):
    try:
        fn()
    except Exception as e:
        print(label, "->", type(e).__name__, ":", str(e)[:70])

attempt("1", lambda: open("/data/ab_tset.csv"))
attempt("2", lambda: open("/data/churn.csv", encoding="cp932").read())
attempt("3", lambda: pd.read_csv("/data/ab_test.csv")["convert"])
attempt("4", lambda: int("1,200"))

出力は、1 -> FileNotFoundError : [Errno 44] No such file or directory: '/data/ab_tset.csv'、2 -> UnicodeDecodeError : 'cp932' codec can't decode byte 0x8d in position 145: illegal multibyt、3 -> KeyError : 'convert'、4 -> ValueError : invalid literal for int() with base 10: '1,200' です。1は ab_test のスペルミス(名前の層)、2は文字コード、3は列名 converted の打ち間違い、4はカンマ入りの文字列(クリック・入力・選択・コピー)です。メッセージの中に、ファイル名、バイト位置、列名、値そのものが書かれています。

ハッシュ値:ファイルの全バイトから計算する固定長の文字列で、内容が同じなら必ず同じ値、1バイトでも違えば(ほぼ確実に)別の値になります。hashlib.sha256(バイト列).hexdigest() は、バイト列(bytes)を受け取り、64文字の16進数の文字列を返します。

バックアップの3-2-1の考え方(一般的な目安):コピーを3つ持ち、2種類の保管先に分け、1つは離れた場所に置く。同じフォルダの中にコピーを置いても、フォルダごと消えたら両方失われます。

段階付き例題:統合演習 ― CSVを読み、確認し、出力し、再読込する

問題:教材の ab_test.csv(架空のA/Bテスト。1行=1ユーザー)を読み込み、行を確認し、結果とノートを出力し、再読込して一致を確かめる。

ステップ1:読み込んで形を確認する(入力→処理)。df.shape(行数・列数のタプル)、df.dtypes(列ごとの型)、欠損の合計を見る。

ステップ2:集計する(処理)。group(A/B)ごとの購入率 converted.mean()。converted は購入したら1、しなければ0の列なので、平均は購入者÷ユーザー数です。分母はユーザー数(各群の行数)で、購入した人だけではありません。

ステップ3:出力して再読込する(出力→検証)。結果をCSV、ノートをテキストに書き、読み直す。

import pandas as pd, tempfile, pathlib
df = pd.read_csv("/data/ab_test.csv")
print(df.shape)
print(df.dtypes.astype(str).to_dict())
print(int(df.isna().sum().sum()))
print(df["group"].value_counts().sort_index().to_dict())
rate = df.groupby("group")["converted"].mean()
print(rate.round(4).to_dict())

out = pathlib.Path(tempfile.mkdtemp())
rate.round(4).to_csv(out / "result.csv", header=["conversion_rate"])
(out / "note.txt").write_text("ab_test.csv: %d rows\n" % len(df), encoding="utf-8")
back = pd.read_csv(out / "result.csv")
print(back)
print(back.shape, (out / "note.txt").read_text(encoding="utf-8").splitlines()[0])
print(round((rate["B"] - rate["A"]) * 100, 2))

出力は次のとおりです。

ステップ4:意味を言葉にする。9.55%と10.81%の差は「1.26ポイント」で、「1.26%の上昇」ではありません(割合の差と、割合そのものの変化率は別の量)。この差が偶然か意味のある違いかは、この授業では判断しません。ここでは、読み込み・確認・出力・再読込の手順が正しく回ることを確認しました。

操作して理解する:バックアップを取り、同じか確かめ、壊れた例を見る

次のコードで、(1) 日付付きの名前でコピー、(2) ハッシュ値の比較、(3) 途中で切れたコピーの検出、(4) フォルダごと消えたときの被害、を順に確認します。

import hashlib, shutil, tempfile, pathlib
root = pathlib.Path(tempfile.mkdtemp())
src = root / "a.csv"
src.write_text("id\n1\n2\n", encoding="utf-8")

def sha(p):
    return hashlib.sha256(pathlib.Path(p).read_bytes()).hexdigest()

print(sha(src)[:16])
(root / "bk").mkdir()
dst = shutil.copy(src, root / "bk" / "a_2026-10-10.csv")
print(sha(src) == sha(dst))

dst2 = root / "bk" / "a_trunc.csv"
dst2.write_text("id\n1\n")
print(sha(src) == sha(dst2), len(src.read_bytes()), len(dst2.read_bytes()))

shutil.rmtree(root)
print(src.exists(), pathlib.Path(dst).exists())

出力は、1d1c91d15ace6e21(ハッシュの先頭16文字)、True(正しいコピーは一致)、False 7 5(途中で切れたコピーは不一致、7バイトと5バイト)、False False(フォルダごと消すと、元もコピーも両方なくなる)です。

考えてみる:

実際の画面では、ファイルのプロパティで「サイズ」を比べるだけでも、途中で切れたコピーを見つけられます。バックアップは取ったら、同じかどうかを確かめて初めて、取れたことになります。

発展(任意):復元の手順と、質問の書き方

この節は任意です。ON01の目標(ここまでの手順を使って、CSVを読み、結果を保存し、再読込で確かめる)は、前の節までで達成できます。

復元の手順(バックアップから元に戻す):

  1. 現状を残す:壊れたファイルを上書きせず、別の名前(例:broken_ を付ける)で退避する。
  2. 復元元を選ぶ:日付とハッシュ値で、どのバックアップが正しいか確認する。
  3. 別の場所に復元する:いきなり元の場所に戻さず、作業用フォルダで中身を確認する。
  4. 確認してから置き換える:行数や代表値が、記録と合うことを確かめる。
  5. 記録する:いつ、どの版から戻したか。

復元の練習をしていないバックアップは、取れたかどうかが分かりません。定期的に、小さなファイルで復元の練習をします。

質問の書き方:他の人に助けを求めるときは、次の5点を書くと解決が早くなります。(1) したかったこと、(2) 実際に起きたこと(エラー文の全文)、(3) 再現手順、(4) 環境(OS、ブラウザ、版)、(5) すでに試したこと。個人情報や機密を含む部分は、伏せてから共有します。

よくある失敗

失敗1:エラー文を読まずに、同じ操作を繰り返す

誤った対応:KeyError が出たので、ファイルを開き直す、再実行する、を繰り返した。

import pandas as pd
df = pd.read_csv("/data/ab_test.csv")
print(list(df.columns))
try:
    df["convert"]
except KeyError as e:
    print("KeyError:", e)
print("converted" in df.columns)

出力は ['user_id', 'group', 'device', 'visits', 'converted', 'revenue']、KeyError: 'convert'、True です。エラー文に、探した名前('convert')が書かれており、実際の列名(converted)は列の一覧で確認できます。

直し方:エラー名とメッセージを書き写し、df.columns などで実際にある名前を確かめる。再実行を繰り返す前に、読む。

失敗2:バックアップを元のファイルと同じフォルダに置く

誤った運用:data フォルダの中に data_backup.csv を作り、バックアップのつもりになった。

import tempfile, shutil, pathlib
root = pathlib.Path(tempfile.mkdtemp())
data = root / "data"
data.mkdir()
(data / "data.csv").write_text("id\n1\n", encoding="utf-8")
shutil.copy(data / "data.csv", data / "data_backup.csv")
shutil.rmtree(data)            # フォルダごと削除(誤操作)
print((data / "data.csv").exists(), (data / "data_backup.csv").exists())

出力は False False です。コピーが同じ場所にあると、同じ原因(フォルダの削除、ディスクの故障)で同時に失われます。

直し方:別のフォルダ、できれば別のドライブや別のサービスに置く(3つのコピー、2種類の保管先、1つは離れた場所)。

失敗3:バックアップを取っただけで、同じか確かめない

誤った運用:コピー中に処理が止まり、途中までしかない report_backup.csv ができたが、気付かず安心した。

import hashlib
orig = ("id,amount\n" + "\n".join(f"{i},{i*100}" for i in range(1, 6)) + "\n").encode()
partial = orig[:25]
print(len(orig), len(partial))
print(hashlib.sha256(orig).hexdigest() == hashlib.sha256(partial).hexdigest())

出力は 40 25(バイト数)と False です。サイズも内容も違います。

直し方:バックアップのあとで、サイズとハッシュ値を比べる。行数や代表値(合計など)も、元と照合して記録する。

まとめ

用語

例外(exception)

Pythonの実行中に起きたエラー。名前(FileNotFoundError など)とメッセージで原因の手がかりを示す。

切り分け(troubleshooting / isolation)

原因の候補を層ごとに1つずつ確かめて絞り込む作業。

ハッシュ値(hash value)

ファイルの全バイトから計算する固定長の文字列。内容が同じなら同じ値になる。

バックアップ(backup)

元のデータが失われても戻せるように、別の場所に作っておくコピー。

DataFrame(DataFrame)

pandasの表データ。行と列を持ち、列ごとに型がある。

よくある質問

エラーメッセージが英語で、読めません。どうすればよいですか?

全部を訳す必要はありません。例外の名前(FileNotFoundError など)と、メッセージの中の固有の語(ファイル名、列名、値)を拾います。名前だけで、前の表のどの層かが分かるようになります。翻訳ツールを使うときは、個人情報を含む部分を伏せてください。

バックアップはどのくらいの頻度で取るべきですか?

失ったときに、やり直せる量で決めます。1日分の作業を失っても許容できないなら、毎日です。節目(分析の前、大きな編集の前)に取る習慣が基本で、頻度は組織のルールに従います。

クラウドの同期サービスは、バックアップになりますか?

完全にはなりません。誤った編集や削除も同期されるからです。ただし、履歴機能やごみ箱で戻せる場合もあります。履歴の保存期間は変わり得るので、公式情報で確認し、重要なものは別の場所にもコピーを持ちます。

ハッシュ値とは、何を保証するのですか?

内容が同じなら同じ値、違えば(ほぼ確実に)違う値になることです。コピーが同一かの確認に使えます。ただし、「中身が正しいか」「安全か」までは保証しません。

エラーが再現しないときは、どうすればよいですか?

そのときの環境、手順、入力ファイルを記録します。再現しない場合も、日時、画面の状況、エラー文を残しておくと、次に出たときに比べられます。偶然に任せて放置せず、記録を残すことが大切です。

仕事で「動かない」と相談されたら、まず何を聞きますか?

(1) 何をしようとしたか、(2) エラー文の全文、(3) 前は動いていたか、(4) 何が変わったか、(5) 環境(OS、ブラウザ)を聞きます。そのうえで、層を一つずつ確認します。ここで質問を整理できる力が、DX推進の仕事で役に立ちます。

確認問題

問1 エラーが出たとき、最初にすべきことはどれか。

  1. ① PCを再起動する
  2. ② エラーの名前とメッセージを最後まで読み、書き写す
  3. ③ ファイルを削除して作り直す
  4. ④ 同じ操作を何度か繰り返す
解答と解説

正解:②

エラー文には、原因の手がかり(ファイル名、列名、値、位置)が書かれています。読まずに操作すると、状況を悪化させることがあります。

問2 KeyError: 'convert' が出た。最も可能性が高い原因はどれか。

  1. ① ファイルが見つからない
  2. ② 文字コードが違う
  3. ③ メモリが足りない
  4. ④ 探した列名 convert が存在せず、実際は converted などのスペル違い
解答と解説

正解:④

KeyError は、辞書や表で、指定した名前が無いときに出ます。メッセージの中の名前と、実際の列名を比べます。

問3 切り分けで「1度に変えるのは1か所」とするのはなぜか。

  1. ① 複数を同時に変えると、どの変更が効いたのか分からなくなるから
  2. ② 操作の回数を増やすため
  3. ③ エラーを隠すため
  4. ④ ルールとして決まっているだけで、理由はない
解答と解説

正解:①

原因を特定し、次に同じ問題が出たときに再利用するためです。複数を同時に変えると、偶然直った場合も原因が分かりません。

問4 バックアップを、元のファイルと同じフォルダに data_backup.csv として置いた。この運用の最大の問題はどれか。

  1. ① ファイル名が長いこと
  2. ② 拡張子が同じこと
  3. ③ フォルダの削除やディスクの故障で、元とコピーが同時に失われること
  4. ④ ファイルサイズが倍になること
解答と解説

正解:③

同じ場所にあるコピーは、同じ原因でまとめて失われます。別の場所、できれば別種類の保管先に置きます。

問5 コピーが元と同じ内容か確かめる方法として、最も確実なものはどれか。

  1. ① ファイル名が同じことを確認する
  2. ② 更新日時を見る
  3. ③ ファイルを開いて、最初の1行だけ見る
  4. ④ ハッシュ値(sha256 など)を比べる
解答と解説

正解:④

ハッシュ値は全バイトから計算するので、1バイトの違いも検出できます。名前、日時、先頭行では、途中で切れたコピーを見逃すことがあります。

問6 except ValueError を except UnicodeDecodeError より先に書くと、何が起こるか。

  1. ① UnicodeDecodeError は発生しなくなる
  2. ② UnicodeDecodeError も ValueError の分岐に入ってしまう
  3. ③ プログラムが動かなくなる
  4. ④ 何も変わらない
解答と解説

正解:②

UnicodeDecodeError は ValueError のサブクラスなので、先に ValueError を書くとそこで捕まります。具体的な型を先に書きます。

次に学ぶこと

これでON01の6授業は終わりです。次は、総合テストと自力課題で到達度を確認します。その後は、データの1行が何を表すかを学ぶ 表・単位・割合・グラフ や、表計算の基本を扱う授業へ進めます。前の授業に戻るなら、保存先は 保存・ダウンロード・アップロード、文字コードは 文字コードと安全なファイル確認 です。

この授業の確認問題だけでモジュールの習得とはしません。ON01 の総合テストと、CSVを使った自力課題で判定します。

キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。

アプリを無料で開く有料版と無料版の違い