例として以下のようなディレクトリ構造があるとして、main.pyはlib.pyをインポートして実行する場合、
lib.pyで相対importや相対パスでファイルを入出力すると、main.pyから見たパスで実行されることになると思います。
このような場合、lib.pyのような他のディレクトリにあるファイルから使われるファイルでは相対importや相対パスは使うべきではなく、絶対パスを常に使うべきなのでしょうか?
hoge ├── main.py └── libs └── lib.py
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
「相対import」は、「相対パスで他のモジュールをインポートするもの」ではありません。
その証拠に、例えば、
hoge.py
1# coding: utf-8 2 3from .piyo import Piyo
という「hoge.py
」と、同じディレクトリに「piyo.py
」があったとして、「python3 hoge.py
」と実行すると、
Traceback (most recent call last): File "hoge.py", line 3, in <module> from .piyo import Piyo ImportError: attempted relative import with no known parent package
というように、ImportErrorが発生します。
相対パスとしては正しいはずなのに、おかしいですよね。
「相対import」というのは、「同パッケージにある他のモジュールをインポートするもの」です。
ここで、「『パッケージ』って何?」という話になると思いますが、パッケージとは、複数のモジュールをひとまとめにしたものです。
というと曖昧ですのでもっと具体的にいうと、sys.path
に格納されているパスにあるディレクトリ一つ一つが一つのパッケージになります。
ですので、パッケージのディレクトリ内にある各モジュールがお互いを呼び出す場合には相対importを、他のパッケージのモジュールを呼び出す場合には絶対importを使用します。可読性の問題ではありません。
もう一つ知っておかなければならないのは、スクリプトを実行した際に、最初に起動したスクリプトがあるディレクトリがsys.path
に追加されることです。
これはつまり、最初に起動したスクリプトと同じディレクトリにあるサブディレクトリは、一つ一つパッケージなることになります。
hoge ├── main.py └── libs └── lib.py
例えば上記の場合、「python3 hoge/main.py
」と実行した際には、「main.py
」と同じディレクトリにある「libs
」ディレクトリが一つのパッケージになります。
ですので、「main.py
」が「libs
」ディレクトリ以下にあるスクリプトをインポートする場合には絶対importで、「libs
」ディレクトリ以下にあるスクリプトがお互いをインポートする場合には相対importで行うのが望ましいことになります。
相対importを使うかどうかは、「どのディレクトリがパッケージになるのか」「どのスクリプトが最初に実行されるのか」が鍵になります。
投稿2021/04/07 14:00
編集2021/04/07 14:01総合スコア3538
0
lib.pyで相対importや相対パスでファイルを入出力すると、main.pyから見たパスで実行されることになると思います。
そんなことはないのでは。
ファイルの入出力を相対パスで書く時はカレントディレクトリが基準で、
相対importはlib.pyの場所が基準です。
(というかmain.pyから見たパスが使われるなら、lib.pyから見た場所じゃないということでそれは相対じゃないですよね?)
plain
1hoge 2├── main.py 3└── libs 4 ├── lib.py 5 └── lib_sub.py
とあった時、main.pyが実行スクリプトだとして、lib.pyに
python
1import libs.lib_sub
と書くのが絶対importで、これはsys.pathから探索されます。
上記の場合実行スクリプトのmain.pyがある場所(要はhogeディレクトリ)が基準になると期待して書いています。
それに対して、
python
1from . import lib_sub
とか
python
1from .lib_sub import foo
と書くのが相対importでしょう。
これらはlib.pyがある場所(要はlibsディレクトリ)を基準に探索します。
だいたいにおいて相対importを使う方が自然だと思います。
例えば「ちょっと気が変わってlibsというパッケージ名を別の名前にしたくなった」とか「libsの上にもうひとつ親パッケージを作って hogehoge.libs
と一段深くしたくなった」とかいう時に、相対importが使われていればlib.pyの中を変更する必要がないという利点があるからです。
投稿2021/04/07 12:12
編集2021/04/08 00:43総合スコア11235
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
Python一般論としては間違っていますが、ウェブアプリ限定の話であれば、ウェブサーバーが起動ファイルのディレクトをカレントディレクトリに設定するはずなので、別に良いのではないでしょうか。
Pythonに限らずHTMLタグの中にパスを書く時と同じ考えで。
ディレクトリ構成を変える時に、まとめて移動するはずのファイル群の中では(相対位置が不変なので)相対パスで、その外は絶対パスですね。
投稿2021/04/07 11:49
編集2021/04/07 11:51総合スコア85901
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
再利用を考えるなら、ファイルを入出力する場合は、相対パスであれ絶対パスであれ、lib.pyでは指定してはだめでしょう。lib.pyで定義する関数がファイルを読み書きするのであれば、それは関数の引数として受け取るようにすれば再利用がしやすくなります。
再利用しないのであれば、ご自身の好きなように書けばよいでしょう。
投稿2021/04/07 11:39
総合スコア24670
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。