0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Python]フォルダ・ファイルのパスを文字列で取得する方法比較(os.getcwd()、__file__、os.path.dirname(__file__))

Last updated at Posted at 2022-08-04

以前の記事を書いたとき、うまく動作しないPythonスクリプトがあった。
ファイル名の取得方法が誤っているのだろうと推定し、修正することで狙い通りの動作をするようになった。
その不具合・正常動作の理由を実験で確認したのでメモしておく。

要点
実験
Python 3.8.10 の場合
Python 3.8.10 1つ上のディレクトリから実行
Python 3.8.10 まとめ
Python 3.10.6 の場合
Python 3.10.6 1つ上のディレクトリから実行
Python 3.10.6 まとめ
パス文字列の結合
おまけ1
おまけ2
参考

要点

  • os.getcwd()__file__でパスを取得。
  • os.path.join()でパスを結合。
  • __file__の仕様がPython3.8以前・Python3.9以降で変更されている。

実験

以下のスクリプトを実行し、出力結果を比較する。

get_names.py
import os

print(os.getcwd())
print(__file__)
print(os.path.dirname(__file__))

Python 3.8.10 の場合

以前の記事を書いた時点で入っていたPythonのバージョンがこれだった。

> python C:\Users\(略)\test\get_names.py
C:\Users\(略)\test
C:\Users\(略)\test\get_names.py
C:\Users\(略)\test
> python get_names.py
C:\Users\(略)\test
get_names.py
                (※空行が出力される)
> python .\get_names.py
C:\Users\(略)\test
.\get_names.py
.

いかにも不具合の種になりそうな差異が見られる。

Python 3.8.10 1つ上のディレクトリから実行

別ディレクトリから実行するとどうなるか。

> python C:\Users\(略)\test\get_names.py
C:\Users\(略)
C:\Users\(略)\test\get_names.py
C:\Users\(略)\test
> python test\get_names.py  
C:\Users\(略)
test\get_names.py
test
> python .\test\get_names.py
C:\Users\(略)
.\test\get_names.py
.\test

Python 3.8.10 まとめ

  • os.getcwd()は実行時のカレントディレクトリを取得。
  • __file__には実行時に指定した文字列がそのまま格納されている。
  • os.path.dirname(__file__)__file__から最後のファイル名を除いた部分を取得する。

Python 3.10.6 の場合

執筆時点での最新版。

> python C:\Users\(略)\test\get_names.py
C:\Users\(略)\test
C:\Users\(略)\test\get_names.py
C:\Users\(略)\test
> python get_names.py
C:\Users\(略)\test
C:\Users\(略)\test\get_names.py
C:\Users\(略)\test
> python .\get_names.py
C:\Users\(略)\test
C:\Users\(略)\test\get_names.py
C:\Users\(略)\test

Python 3.10.6 1つ上のディレクトリから実行

同様に比較。

> python C:\Users\(略)\test\get_names.py
C:\Users\(略)
C:\Users\(略)\test\get_names.py
C:\Users\(略)\test
> python test\get_names.py  
C:\Users\(略)
C:\Users\(略)\test\get_names.py
C:\Users\(略)\test
> python .\test\get_names.py
C:\Users\(略)
C:\Users\(略)\test\get_names.py
C:\Users\(略)\test

Python 3.10.6 まとめ

  • __file__が常にフルパスになった。
  • ファイルのあるディレクトリで実行するなら、os.getcwd()__file__は同じ文字列になる。

特に理由が無ければPython3.9以降を使うほうが不具合を避けられるだろう。

パス文字列の結合

パス文字列を結合する際はos.path.join()を使う。
OS毎の区切り文字の差異(/or\)に対応するなど、安全にパス文字列を操作できる。

使用例。
詳細は以前の記事を参照。

use_rs.py
import os
from ctypes import cdll

libfile = "rs_add.dll"
cwd = os.getcwd()
libpath = os.path.join(cwd, libfile)

rslib = cdll.LoadLibrary(libpath)
print(rslib.rs_add(4, 6))

おまけ1

VS Codeの「右クリック → ターミナルでPythonファイルを実行する」の方法で実行すると、コマンドの前に&マークが付いていることに気づいた。
PowerShellの機能らしい。

この方法で実行するとドライブ名が小文字になったり、区切り文字が\/と変化したりする。
手入力で実行する場合でも同様。
一応注意しておく。

> & python c:/Users/(略)/test/get_names.py
C:\Users\(略)\test
c:/Users/(略)/test/get_names.py
c:/Users/(略)/test

おまけ2

os.path.realpath(__file__)os.path.abspath(__file__)なんてのもあるらしい。

参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?