質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
import

自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

パス

パス(path)はファイルシステムの場所(階層)を明示したものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

12240閲覧

pythonの相対パスや相対importを呼び出されて使われるファイルに書くことは可読性の観点から非推奨なのでしょうか

abea

総合スコア32

import

自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

パス

パス(path)はファイルシステムの場所(階層)を明示したものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2021/04/07 11:24

例として以下のようなディレクトリ構造があるとして、main.pyはlib.pyをインポートして実行する場合、
lib.pyで相対importや相対パスでファイルを入出力すると、main.pyから見たパスで実行されることになると思います。
このような場合、lib.pyのような他のディレクトリにあるファイルから使われるファイルでは相対importや相対パスは使うべきではなく、絶対パスを常に使うべきなのでしょうか?

hoge ├── main.py └── libs └── lib.py

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
katsuko

総合スコア3469

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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
quickquip

総合スコア11038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Python一般論としては間違っていますが、ウェブアプリ限定の話であれば、ウェブサーバーが起動ファイルのディレクトをカレントディレクトリに設定するはずなので、別に良いのではないでしょうか。

Pythonに限らずHTMLタグの中にパスを書く時と同じ考えで。
ディレクトリ構成を変える時に、まとめて移動するはずのファイル群の中では(相対位置が不変なので)相対パスで、その外は絶対パスですね。

投稿2021/04/07 11:49

編集2021/04/07 11:51
otn

総合スコア84505

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

再利用を考えるなら、ファイルを入出力する場合は、相対パスであれ絶対パスであれ、lib.pyでは指定してはだめでしょう。lib.pyで定義する関数がファイルを読み書きするのであれば、それは関数の引数として受け取るようにすれば再利用がしやすくなります。

再利用しないのであれば、ご自身の好きなように書けばよいでしょう。

投稿2021/04/07 11:39

ppaul

総合スコア24666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abea

2021/04/07 11:51

ありがとうございます。 importについてはどうなのでしょう 再利用を考えたときは絶対importの方が良いのでしょうか?
ppaul

2021/04/07 12:10

pythonの寿準ライブラリや拡張ライブラリを見てみてください。 一体として使うものなら相対importしていますね。つまりパッケージとして作るということです。 一体でなければ相対importは使っていませんね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問