FileNotFoundErrorが出てファイル参照迷子になったときの対処について

## はじめに
pythonでサンプルコードを使って遊んでいると
ほぼ100%といっていいほど、ファイル読み込みのくだりで
「FileNotFoundError」が発生するかわいそうな状況になる。

いつまでも成長しないのは反省を記録に残さないからだとおもったので
記録に残す

## 今回のかわいそうな状況
本来であればセキュリティの問題もあるだろうし
自分の散らかったフォルダ構成をみせるのは自分の部屋を人に見せるくらい恥ずかしいけど
これで今後おなじようなことがおこさないためにも
パンツ一枚すら履かない所存で、ありのままでいく。

```:ファイル構成
C:\Users\watya\protos>
├─kagglebook-master
│  ├─ch01
│  │  └─ch01-01-titanic.py
│  ├─・・・
│  ├─input
│  │  └─ch01-titanic
│  │  　├─gender_submission.csv
│  │  　├─test.csv
│  │  　└─train.csv
…　…
```

```:実行したコマンド
C:\Users\watya\protos> & C:/Users/watya/Anaconda3/python.exe c:/Users/watya/protos/kagglebook-master/ch01/ch01-01-titanic.py
```

```python:実行したプログラム（冒頭部のみ）
import numpy as np
import pandas as pd

# -----------------------------------
# 学習データ、テストデータの読み込み
# -----------------------------------
# 学習データ、テストデータの読み込み
train = pd.read_csv('../input/ch01-titanic/train.csv')
test = pd.read_csv('../input/ch01-titanic/test.csv')
```

```:発生したエラー
FileNotFoundError: [Errno 2] File b'../input/ch01-titanic/train.csv' does not exist: b'../input/ch01-titanic/train.csv'
```

## エラーが起きた原因
[実行したコマンド]を見ればわかるけど
実際は
　C:\Users\watya\protos
で実行しているのに、
　c:/Users/watya/protos/kagglebook-master/ch01/
で実行しているものと「勘違い」しているために
　FileNotFoundError
が起きている。

この「勘違い」を踏まえて適切なパス指定ができるよう落ち着いた対応ができればいいのだと思う。

## 対処①：まずは今どこで実行している？を理解して落ち着きをとりもどす
参考：https://note.nkmk.me/python-os-getcwd-chdir/

カレントディレクトリを取得・確認: os.getcwd()を使う

こんな感じで使うとよい

```python:実行ファイル
import numpy as np
import pandas as pd
import os

print("現在地:{}".format(os.getcwd())) ←ココに差し込む

# -----------------------------------
# 学習データ、テストデータの読み込み
# -----------------------------------
# 学習データ、テストデータの読み込み
train = pd.read_csv('../input/ch01-titanic/train.csv')
test = pd.read_csv('../input/ch01-titanic/test.csv')
```

```:実行結果
PS C:\Users\watya\protos> & C:/Users/watya/Anaconda3/python.exe c:/Users/watya/protos/kagglebook-master/ch01/ch01-01-titanic.py
現在地:C:\Users\watya\protos　←pd.read_csv()がどこからファイルを参照したのかがわかる
Traceback (most recent call last):
・・・
FileNotFoundError: [Errno 2] File b'../input/ch01-titanic/train.csv' does not exist: b'../input/ch01-titanic/train.csv'
```
これがあれば最悪、パニックは回避できる。
現在地がわかれば「なるほどね、全然違うところから参照しているからダメなんだ」ということがわかるので解決の方向は見える。


## 対処②：適切なパス指定をしてファイル参照できるようにする
やり方はいくつかあると思ってるのでパッと思いついたやつ全部書いた（もっとあると思うけど…）
①read_csv()の引数を相対パスにせず絶対パス指定にしてやる
②実行時のパスを実行ファイルのところまで移動してから実行する
　つまり
　　C:\Users\watya\protos>
　ではなく
　　C:\Users\watya\protos/kagglebook-master/ch01/>
  で実行する
③os.chdir()を使って実行後に実行ディレクトリを移動して参照する

どれでもいいっちゃいいけど、個人的にはプライドも何もあったものじゃないけど
コード丸パクリをよくするので、①のようにパクったコードはいじるのは避けたいので
③で追記するってのが個人的には好き。

コードいじらなくて済むのであれば②が一番コード触らないのでキレイだけど
移動のひと手間は物忘れの激しい自分の場合、ここをさぼってよく迷子になるので
性格的には③が向いていると思う。

…とつべこべ書いたところで、①②のコードがどうなるのかを書く。

```python:実行ファイル（①の場合）
import numpy as np
import pandas as pd

# -----------------------------------
# 学習データ、テストデータの読み込み
# -----------------------------------
# 学習データ、テストデータの読み込み
train = pd.read_csv('c:/Users/watya/protos/kagglebook-master/input/ch01-titanic/train.csv') ←ここを書き直した
test = pd.read_csv('c:/Users/watya/protos/kagglebook-master/input/ch01-titanic/test.csv') 　←ここを書き直した
```

```python:実行ファイル（③の場合）
import numpy as np
import pandas as pd
import os

os.chdir('kagglebook-master/ch01/') ←ココに差し込む

# -----------------------------------
# 学習データ、テストデータの読み込み
# -----------------------------------
# 学習データ、テストデータの読み込み
train = pd.read_csv('../input/ch01-titanic/train.csv')
test = pd.read_csv('../input/ch01-titanic/test.csv')
```


## 番外編：assert文を使う
今回はファイル参照迷子になったときの対処なので
ちょっと話がズレるけど、os.getcwd()はあくまでデバグで使うような露骨な手段だし
普通、こんなFileNotFoundErrorを吐き出すようなコードを書くこと自体いかがなものか…と思い
assert文でちゃんエラーを受け止める方法も書き残す。

```python:実行ファイル
import numpy as np
import pandas as pd
import os

# csvファイル有無チェック
assert os.path.isfile('../input/ch01-titanic/train.csv'), 'train.csv がない'
assert os.path.isfile('../input/ch01-titanic/test.csv'), 'test.csv がない'

# -----------------------------------
# 学習データ、テストデータの読み込み
# -----------------------------------
# 学習データ、テストデータの読み込み
train = pd.read_csv('../input/ch01-titanic/train.csv')
test = pd.read_csv('../input/ch01-titanic/test.csv')
```

```:実行結果
PS C:\Users\watya\protos> & C:/Users/watya/Anaconda3/python.exe c:/Users/watya/protos/kagglebook-master/ch01/ch01-01-titanic.py
Traceback (most recent call last):
  File "c:/Users/watya/protos/kagglebook-master/ch01/ch01-01-titanic.py", line 9, in <module>
    assert os.path.isfile('../input/ch01-titanic/train.csv'), 'train.csv がない'
AssertionError: train.csv がない
PS C:\Users\watya\protos>
```

大分スッキリした感じ。ただ、これだけでは結局なんでファイルがないんだーってなるので
何の解決にもなってないが、ひとまず猛烈なFileNotFoundErrorを吐き出すようなことはない。

## おわりに
我ながらなんてレベルの低い記事を書いているんだ…と思ったけど
これが今のレベルなんだということは受け入れたほうがいいんだと思う。

それとこんだけ書けばさすがの自分も覚えたし、今度また忘れてしまっても
Qiitaで「FileNotFoundError」で検索したら自分の記事が引っかかるので
これでもう安心だ！

～おしまい～