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()
でスクリプト名のディレクトリを作成する
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のスクリプトの名前は以下のようにして取得できます。
import os
print(os.path.basename(__file__))
# main.py
今回は拡張子を除いたファイル名を利用するので、rstrip()
を使います。
current_name = os.path.basename(__file__)
current_name = current_name.rstrip('.py')
print(current_name)
# main
実際にファイルを書き出します。
その後、glob
を使ってファイルを確認します。
with open(f'{current_name}_output.txt', mode='w')as f:
f.write('something')
import glob
print(glob.glob('*.txt'))
# ['main_output.txt']
保存したファイル名に実行中のスクリプト名が挿入されました。
複数ファイルの場合
1つのファイルだけだとメリットがわかりづらいので、
次は複数のファイルを作成します。
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']
100個以上のファイルの並び替えを想定して、
{i+1:03}
を使って3桁になるように0埋めを行っています。
さらに、別のスクリプトでもファイルを書き出して、結果を出力してみます。
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']
ファイルにスクリプト名と連番を振ったおかげで、ディレクトリの見通しがよくなりました。
新しくディレクトリをつくる場合
いくらファイル名を工夫しても、ファイルを大量に書き出す場合は、
スクリプトと同じ階層に書き出すと、ディレクトリの中がごちゃごちゃしてしまいます。
見通しをよくするために新しいディレクトリを作成します。
スクリプト名を挿入する手順はファイル作成時とほぼ同じです。
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/']
すでに同名のディレクトリがあるとエラーが起きるので、
先にディレクトリの有無をos.path.exists()
で調べています。
先ほどと同様に複数のファイルを作成してみます。
今回は保存先を新しく作成したディレクトリの下に設定しています。
#%%
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
まとめ
- 複数のスクリプトでファイルを書き出すときの命名が楽になった!
- どのスクリプトで実行したかがわかるので、再現性が高まる(はず)
コード全文
コード全体(クリックで表示)
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')))
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')