書き出すファイルの名前に､書き出しを実行したPythonファイルの名前を自動で挿入する方法

Pythonでファイルを書き出すときに､保存するファイルに簡単に名前をつけるコードを書いたので記事にします｡
具体的には､**実行しているPythonのファイル名をそのまま保存するファイルの名前に流用**します｡

コード全文は記事の末尾に記載しています(コピペ用)｡

筆者はデータ分析で`matplotlib`で作成したグラフなどの保存の際にこの方法を使いました｡
ファイル名に一定のルールを設け､命名を自動化することは結果の再現性にもつながります｡

# 本記事の想定読者
- Pythonユーザー
- 複数のスクリプトを使って図などを書き出すことがある
- 保存したファイルの整理に苦労することがある

# 最終的なアウトプットの例
今回は簡単のためにテキストファイルを例に使います｡

`main.py`と`sub.py`からファイルを書き出す場合を考えます｡
本記事の方法を使うと､以下のようなディレクトリ構成を自動でつくることができます｡
```:最終的なディレクトリ構成
.
├── main
│   ├── 001_output.txt
│   ├── 002_output.txt
│   └── 003_output.txt
├── main.py
├── main_001_output.txt
├── main_002_output.txt
├── main_003_output.txt
├── sub.py
├── sub_001_output.txt
├── sub_002_output.txt
└── sub_003_output.txt
```
# 概要
- `os.path.basename(__file__)`で実行中のスクリプト名を取得する
- f文字列を使って保存するファイルにスクリプト名を含んだファイル名を設定する
- `os.mkdir()`でスクリプト名のディレクトリを作成する

```python:サンプルコード
import os

current_name = os.path.basename(__file__)
current_name = current_name.rstrip('.py')

if not os.path.exists(current_name):
    os.mkdir(current_name)

for i in range(3):
    with open(f'{current_name}/{i+1:03}_output.txt', mode='w')as f:
        f.write('something')
```

# コードの説明
## スクリプト名の取得とファイルの書き出し
実行中のPythonのスクリプトの名前は以下のようにして取得できます｡

```python:main.py
import os

print(os.path.basename(__file__))
# main.py
```

今回は拡張子を除いたファイル名を利用するので､`rstrip()`を使います｡
```python:main.py
current_name = os.path.basename(__file__)
current_name = current_name.rstrip('.py')
print(current_name)
# main

```
実際にファイルを書き出します｡
その後､`glob`を使ってファイルを確認します｡
```python:main.py
with open(f'{current_name}_output.txt', mode='w')as f:
    f.write('something')

import glob
print(glob.glob('*.txt'))
# ['main_output.txt']
```

保存したファイル名に実行中のスクリプト名が挿入されました｡

## 複数ファイルの場合
1つのファイルだけだとメリットがわかりづらいので､
次は複数のファイルを作成します｡

```python
for i in range(3):
    with open(f'{current_name}_{i+1:03}_output.txt', mode='w')as f:
        f.write('something')

print(sorted(glob.glob('*.txt')))
# ['main_001_output.txt', 'main_002_output.txt', 'main_003_output.txt', 'main_output.txt']
```
:::note info
100個以上のファイルの並び替えを想定して､
`{i+1:03}`を使って3桁になるように0埋めを行っています｡
:::

さらに､別のスクリプトでもファイルを書き出して､結果を出力してみます｡
```python:sub.py
import os
import glob

for i in range(3):
    with open(f'{current_name}_{i+1:03}_output.txt', mode='w')as f:
        f.write('something')

print(sorted(glob.glob('*.txt')))
# ['main_001_output.txt', 'main_002_output.txt', 'main_003_output.txt', 'main_output.txt',
# 'sub_001_output.txt', 'sub_002_output.txt', 'sub_003_output.txt']
```
ファイルにスクリプト名と連番を振ったおかげで､ディレクトリの見通しがよくなりました｡

## 新しくディレクトリをつくる場合
いくらファイル名を工夫しても､ファイルを大量に書き出す場合は､
スクリプトと同じ階層に書き出すと､ディレクトリの中がごちゃごちゃしてしまいます｡

見通しをよくするために新しいディレクトリを作成します｡
スクリプト名を挿入する手順はファイル作成時とほぼ同じです｡
```python
current_name = os.path.basename(__file__)
current_name = current_name.rstrip('.py')

if not os.path.exists(current_name):
    os.mkdir(current_name)

print(glob.glob('*/'))
# ['main/']

```
:::note info
すでに同名のディレクトリがあるとエラーが起きるので､
先にディレクトリの有無を`os.path.exists()`で調べています｡
:::

先ほどと同様に複数のファイルを作成してみます｡
今回は保存先を新しく作成したディレクトリの下に設定しています｡

```python
#%%
for i in range(3):
    with open(f'{current_name}/{i+1:03}_output.txt', mode='w')as f:
        f.write(f'something')

print(sorted(glob.glob('main/*.txt')))
# ['main/001_output.txt', 'main/002_output.txt', 'main/003_output.txt']
```
狙いどおり`main/`の下にファイルが作成されたことを確認できました｡

## 最終的なディレクトリ構成

```:最終的なディレクトリ構成(再掲)
.
├── main
│   ├── 001_output.txt
│   ├── 002_output.txt
│   └── 003_output.txt
├── main.py
├── main_001_output.txt
├── main_002_output.txt
├── main_003_output.txt
├── sub.py
├── sub_001_output.txt
├── sub_002_output.txt
└── sub_003_output.txt
```

# まとめ
- 複数のスクリプトでファイルを書き出すときの命名が楽になった！
- どのスクリプトで実行したかがわかるので､再現性が高まる(はず)

# コード全文
<details><summary>コード全体(クリックで表示)</summary>

```Python:main.py
import os
import glob

current_name = os.path.basename(__file__)
current_name = current_name.rstrip('.py')
print(current_name)


with open(f'{current_name}_output.txt', mode='w')as f:
    f.write('something')
print(glob.glob('*.txt'))


for i in range(3):
    with open(f'{current_name}_{i+1:03}_output.txt', mode='w')as f:
        f.write(f'something')
print(sorted(glob.glob('*.txt')))


if not os.path.exists(current_name):
    os.mkdir(current_name)
print(glob.glob('*/'))


for i in range(3):
    with open(f'{current_name}/{i+1:03}_output.txt', mode='w')as f:
        f.write(f'something')
print(sorted(glob.glob('main/*.txt')))
```

```Python:sub.py
import os

current_name = os.path.basename(__file__)
current_name = current_name.rstrip('.py')

for i in range(3):
    with open(f'{current_name}_{i+1:03}_output.txt', mode='w')as f:
        f.write(f'something')

```

</details>