Pythonプロジェクトで相対パスを使用してファイルを読み取る 質問する

Pythonプロジェクトで相対パスを使用してファイルを読み取る 質問する

次のような構造の 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 バージョンを移動しました]

おすすめ記事