よちよちpython

独習 python/Qpython/Pydroid3/termux/Linux

実行ファイル自身のファイルパスを取得する__file__

別ファイルの読み書きをするようなプログラムの場合のファイルパスの指定についてのメモ。
基本的なことですが意外と落とし穴…🕳️



実行ファイルの保存場所と、実行する場所(カレントディレクトリ)は必ずしも一致している訳ではありません。単に「print()」や「return」で戻り値を返すだけならディレクトリを気にする必要は特に無さそうですが、別ファイルの読み書きをするような場合は注意がいります。変な所に保存されたり…



カレントディレクトリを表示するos.getcwd()


とりあえずカレントディレクトリについて。
実行する場所をワーキングディレクトリカレントディレクトリと言います。
GUI上でマウスを使って操作する時はカレントディレクトリをほとんど気にしませんが、コマンドやプログラムを使っての操作の場合は無視できません。思ってたのと違う動きをすることがよくある。
カレントディレクトリを調べるには、コマンドでは



Pythonではos.getcwd()
こんな感じで

import os

print(os.getcwd())

実行ファイルの保存場所とは関係なく、ファイルを実行する時のカレントディレクトリが表示される。
「何処でこれを実行したか」の表示。



ファイル自身の保存場所を表示するfile


たとえば、別ファイルを書き出すプログラム

s = "うんこ"
filename = "toilet.txt"

with open(filename, "w") as f:
    f.write(s)

このプログラムを「プログラムフォルダ」の中に作った「プロジェクトフォルダ」に保存したとします。
で、ホームディレクトリなどの別な場所からファイルパスを指定してこれを実行した。書き出された別ファイルは実行ファイルの保存場所と同じ「プロジェクトフォルダ」に保存されると思いきや、実行したカレントディレクトリに保存される
よって、このファイルを色んな所から実行する度に「うんこ」と書かれたファイルを散らかすことに…。💩



実行ファイル自身の保存場所を表示するには、

print(__file__)
$ python here.py
/な/ん/と/か/here.py

これは先ほどと違い、「何処で実行しても、ファイル自身の保存場所(絶対パス)を表示」する。



これを使って、別ファイルを実行ファイルと同じディレクトリに保存できる。



パスのディレクトリ部分を抜き出すos.path.dirname(file)


実行ファイルの絶対パスディレクトリ部分だけを抜き出すには次のようにする。

import os

print(os.path.dirname(__file__))

「/な/ん/と/か/here.py」の「/な/ん/と/か/」の部分だけが表示される。



自身のファイル名だけを表示するos.path.basename(file)


import os

print(os.path.basename(__file__))

「/な/ん/と/か/here.py」から「here.py」だけが表示される。



パスを結合するos.path.join(ディレクトリ, ファイル名)


ディレクトリのパスと、ファイル名を結合して「/ディレクトリ/ファイル名.py」のようなパスを作るには、たとえば

import os

dirname = "/ディレクトリ/"
basename = "ファイル名.py"

print(os.path.join(dirname, basename))



実行ファイルと同じ場所に別ファイルを書き出す例


実行ファイル自身の保存場所と同じディレクトリに別ファイルを書き出したい時は、

import os

# 書き出すディレクトリ(__file__と同じ場所)
dirname = os.path.dirname(__file__)

# 書き出すファイル名
basename = "gogo.txt"

# 書き出すファイルパスの結合
filename = os.path.join(dirname, basename)

# 書き込む文
text = "信長は、どうか"

# ファイルに書き込み
with open(filename, "w") as f:
    f.write(s)

これで、実行ファイルを何処に移動させても、別のPCでも何処ででも、実行ファイルの保存場所と同じ場所に別ファイルが書き出されるように出来た。

読み込む場合も、ファイルの絶対パスを指定するか、または上記のように(__file__)で実行ファイル自身のパスを取得して結合などして行うのが便利と思う。



こういう事は入門書の真ん中あたりに載っている初歩的なことなんだけど、結構ミスの出やすい所なんじゃないかな、知らんけど。

以上です。