私はそれがどのように機能するかをよりよく理解するためにPythonのインポートシステムをプレイしていて、別の問題に遭遇しました。私は次の構造を持っています
pkg/
__init__.py
c.py
d.py
subpkg/
__init__.py
a.py
b.py
内部a.py
には次のコードがあります。
from . import b
from .. import d
そしてc.py
の中には次のものがあります:
import subpkg.a
今、私は次のエラーを受け取ります:
ValueError:トップレベルのパッケージを超えて相対インポートを試みました
しかしなぜ?どうすれば解決できますか? IDLEからc.py
を実行していますが、pkg
には__init__.py
ファイルがあるため、パッケージと見なす必要があります。
最初のインポートは正常に機能しますが、機能しないのは次のとおりです。
from .. import d
なんらかの理由で親パッケージから何かをインポートしようとしているのですが、どうやらできません。
これは私の狂気に疑問を投げかけました。
この問題は、人々が相対インポートをパス相対ではないとして誤って取るという混乱から生じています。
相対インポートは、実行されるファイルの場所によって異なります。
この answer は、pythonモジュールが実際にどのように機能するかを詳しく説明していますが、要約します。
__main__
です。pkg.subpkg.a
from ..
を実行する場合、ファイル名には少なくとも2つのドットが必要です。 from ...
-3ドット。今面白い部分が来ます。
c.pyを直接実行すると、__main__
という名前が付けられ、a.pyにはsubpkg.a
が付きます。
2番目のステートメントのように、subpkg.a
を内部で実行するには、from ..
の名前に少なくとも2つのドットが必要です。
修正
pkgの外に新しいファイルを作成します。たとえば、main.py
pkg/
__init__.py
c.py
d.py
subpkg/
__init__.py
a.py
b.py
main.py
Main.py内
import pkg.c
main.pyを実行すると、名前は__main__
になり、a.pyはpkg.subpkg.a
になります。 2番目のステートメントに従って、名前に2つのドットが含まれるようになり、from ..
を実行できます
もう一つ。 c.pyがモジュールとしてロードされたので、fromを使用してaをロードする必要があります.py。
from .subpkg import a
Python 3はインポートシステムを変更したので、作業中のモジュールの周りにあるモジュールが必要になるたびに、相対的なインポートが必要になります(PYTHONPATH
またはsys.path
)。
ここでの正しい使い方は
from .subpkg import a
IDLEを使用している場合、環境はまったく異なります。したがって、現在の場所をパスに追加して、インポートが再び機能するようにすることができます。
試してください:
sys.path.insert(0, '')
奇妙かもしれませんが、それはより良いもののためです
PS:この最後の方法が機能しない場合-私は現在IDLE環境を持っていません-おそらく作業ディレクトリが正しく設定されていないためです。
代わりにこの回答を試してください: https://stackoverflow.com/a/17361545/754991
私はこの解決策を見つけました:
#! /usr/bin/env python
import os
import sys
sys.path.append(os.path.realpath('.'))
from d import *