Pythonのパスの書き方

pythonコマンドを使ってプログラムを実行した場合のインポートやファイル参照のパスについて、理解できていなかったので、実際に動かして動作を確認しました。
なお、相対パスはpythonコマンドで実行するモジュールでは使えないという制約があります。

fromの指定

ディレクトリ構造

project_root/
|-- main.py
|-- child_dir/
    |-- sub_main.py
    |-- child_module.py
    |-- grandchild_dir/
        |-- grandchild_module.py

ファイルの内容

main.py
from child_dir.child_module import ChildModule

child = ChildModule()
child.put()
child.put_child()
sub_main.py
# ChildModule の import 文

child = ChildModule()
child.put()
child.put_child()
child_module.py
# GrandchildModule の import 文

class ChildModule:
    def put(self):
        print('ChildModule')
    #;

    def put_child(self):
        child = GrandchildModule()
        child.put()
    #;
#;
grandchild_module.py
class GrandchildModule:
    def put(self):
        print('GrandchildModule')
    #;
#;

main.py実行時

project_rootにて、python3 main.pyを実行する。
この時、child_module.pyimport文が以下だと、エラーになる。

from grandchild_dir.grandchild_module import GrandchildModule

child_module.pyから見た相対パスまたは、main.pyから見たパスでgrandchild_moduleを記載すると動作する。

from .grandchild_dir.grandchild_module import GrandchildModule
from child_dir.grandchild_dir.grandchild_module import GrandchildModule

結果

ChildModule
GrandchildModule

child_dir/sub_main.py実行時

次にproject_rootにて、python3 child_dir/sub_main.pyを実行する。
この時、sub_main.pyimport文が以下だと、エラーになる。

from child_dir.child_module import ChildModule
from .child_module import ChildModule

以下のように、実行するモジュールからのパスだと正常に動作する。

from child_module import ChildModule

この時、child_module.pyimport文が以下だと、エラーになる。

from .grandchild_dir.grandchild_module import GrandchildModule
from child_dir.grandchild_dir.grandchild_module import GrandchildModule

以下のように、実行するモジュールからのパスだと正常に動作する。

from grandchild_dir.grandchild_module import GrandchildModule

結果

ChildModule
GrandchildModule

sub_main.py実行時

次にchild_dirにて、python3 sub_main.pyを実行する。
この時の結果はproject_rootpython3 child_dir/sub_main.py実行時と同じだった。

結論

import文はpythonコマンドで実行するモジュールからのパスで記載する。もしくはimportされたファイル側で相対パスを記載する。
また、pythonコマンドで実行するモジュールと同じディレクトリにあるモジュールでも相対パスは使えない。
importされたファイル側と同一ディレクトリにあるモジュールの相対パスを記載時は以下のようにする。
from .パッケージ名 import モジュール名

ファイルパスの指定

ディレクトリ構造

project_root/
|-- main.py
|-- sample.txt
|-- child_dir/
    |-- sub_main.py
    |-- child_module.py
    |-- sample2.txt
    |-- grandchild_dir/
        |-- sample3.txt
        |-- grandchild_module.py
main.py
from __future__ import with_statement
from child_dir.child_module import ChildModule

file_path = 'sample.txt'
with open(file_path, 'r') as f_in:
    file_contents = f_in.read()
#;
print(file_contents)

child = ChildModule()
child.read()
child.read_child()
sub_main.py
from child_module import ChildModule

file_path = 'sample2.txt'
with open(file_path, 'r') as f_in:
    file_contents = f_in.read()
#;
print(file_contents)

child = ChildModule()
child.read()
child.read_child()
child_module.py
from __future__ import with_statement
from .grandchild_dir.grandchild_module import GrandchildModule

file_path = 'sample2.txt'
class ChildModule:
    def read(self):
        with open(file_path, 'r') as f_in:
            file_contents = f_in.read()
        #;
        print(file_contents)
    #;

    def read_child(self):
        child = GrandchildModule()
        child.read()
    #;
#;
grandchild_module.py
file_path = 'sample3.txt'
class GrandchildModule:
    def read(self):
        with open(file_path, 'r') as f_in:
            file_contents = f_in.read()
        #;
        print(file_contents)
    #;
#;

main.py実行時

project_rootにて、python3 main.pyを実行する。
main.pyfile_pathは以下のどちらでも正常に動作する。

file_path = 'sample.txt'
file_path = './sample.txt'

この時、child_module.pyfile_pathは以下だとエラーになる。

file_path = 'sample2.txt'
file_path = './sample2.txt'

以下のように、main.pyから見たパスだと正常に動作する。

file_path = 'child_dir/sample2.txt'
file_path = './child_dir/sample2.txt'

grandchild_module.pyfile_pathは以下だとエラーになる。

file_path = 'sample3.txt'
file_path = './sample3.txt'
file_path = 'grandchild_dir/sample3.txt'
file_path = './grandchild_dir/sample3.txt'

以下のように、main.pyから見たパスだと正常に動作する。

file_path = 'child_dir/grandchild_dir/sample3.txt'
file_path = './child_dir/grandchild_dir/sample3.txt'

child_dir/sub_main.py実行時

次にproject_rootにて、python3 child_dir/sub_main.pyを実行する。
この時、sub_main.pyfile_pathが以下だと、エラーになる。

file_path = 'sample2.txt'
file_path = './sample2.txt'

以下のように、pythonコマンドを実行したディレクトリ(project_root)から見たパスだと正常に動作する。

file_path = 'child_dir/sample2.txt'
file_path = './child_dir/sample2.txt'

同様にchild_module.pyfile_pathもpythonコマンドを実行したディレクトリ(project_root)から見たパスだと正常に動作する。

grandchild_module.pyfile_pathも以下だとエラーになる。

file_path = 'sample3.txt'
file_path = './sample3.txt'
file_path = 'grandchild_dir/sample3.txt'
file_path = './grandchild_dir/sample3.txt'

以下のように、pythonコマンドを実行したディレクトリ(project_root)から見たパスだと正常に動作する。

file_path = 'child_dir/grandchild_dir/sample3.txt'
file_path = './child_dir/grandchild_dir/sample3.txt'

sub_main.py実行時

次にchild_dirにて、python3 sub_main.pyを実行する。
この時、sub_main.pyfile_pathが以下だと、エラーになる。

file_path = 'child_dir/sample2.txt'
file_path = './child_dir/sample2.txt'

次のように、sub_main.pyから見たパスだと正常に動作する。

file_path = 'sample2.txt'
file_path = './sample2.txt'

同様にchild_module.pyfile_pathもpythonコマンドを実行したディレクトリ(child_dir)から見たパスだと正常に動作する。

grandchild_module.pyfile_pathは以下だとエラーになる。

file_path = 'child_dir/grandchild_dir/sample3.txt'
file_path = './child_dir/grandchild_dir/sample3.txt'
file_path = 'sample3.txt'
file_path = './sample3.txt'

次のように、pythonコマンドを実行したディレクトリ(child_dir)から見たパスだと正常に動作する。

file_path = 'grandchild_dir/sample3.txt'
file_path = './grandchild_dir/sample3.txt'

結論

ファイルパスはpythonコマンドを実行するディレクトリからのパスで記載する。
このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

スポンサードリンク

関連コンテンツ

コメント

メールアドレスが公開されることはありません。 が付いている欄は必須項目です