次のような構造の Python プロジェクトがあるとします。
project
/data
test.csv
/package
__init__.py
module.py
main.py
__init__.py
:
from .module import test
module.py
:
import csv
with open("..data/test.csv") as f:
test = [line for line in csv.reader(f)]
main.py
:
import package
print(package.test)
実行するとmain.py
次のエラーが発生します。
C:\Users\Patrick\Desktop\project>python main.py
Traceback (most recent call last):
File "main.py", line 1, in <module>
import package
File "C:\Users\Patrick\Desktop\project\package\__init__.py", line 1, in <module>
from .module import test
File "C:\Users\Patrick\Desktop\project\package\module.py", line 3, in <module>
with open("../data/test.csv") as f:
FileNotFoundError: [Errno 2] No such file or directory: '../data/test.csv'
module.py
ただし、ディレクトリから実行するとpackage
、エラーは発生しません。 で使用されている相対パスは、open(...)
元のファイルが実行される場所 (つまり__name__ == "__main__"
) に対してのみ相対的であるようです。 相対パスのみを使用して、これをどのように処理できますか?
ベストアンサー1
相対パスは現在の作業ディレクトリパスを相対パスにしたくない場合は、絶対パスにする必要があります。
しかし、現在のスクリプトから絶対パスを構築するのによく使われるトリックがあります。__file__
特別な属性:
from pathlib import Path
path = Path(__file__).parent / "../data/test.csv"
with path.open() as f:
test = list(csv.reader(f))
これにはPython 3.4以上が必要です(パスライブラリモジュール)。
古いバージョンをサポートする必要がある場合は、次のようにして同じ結果を得ることができます。
import csv
import os.path
my_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(my_path, "../data/test.csv")
with open(path) as f:
test = list(csv.reader(f))
[2020年編集:python3.4+ が標準になるはずなので、まず jpyams のコメントを参考にして pathlib バージョンを移動しました]