[解決済み] 億の相対的輸入
質問事項
私はここに来たことがあります。
- http://www.python.org/dev/peps/pep-0328/
- http://docs.python.org/2/tutorial/modules.html#packages
- Python パッケージ: 相対インポート
- python 相対インポートのサンプルコードが動作しない
- Python 2.5 における相対インポート
- Pythonにおける相対的インポート
- Pythonです。相対インポートの無効化
とコピーしなかったURLがたくさんあります。SOでも他のサイトでも、すぐに解決できると思っていた頃です。
永遠に続く疑問はこれです:この "Attempted relative import in non-package" のメッセージはどうすれば解決するのでしょうか?
ImportError: attempted relative import with no known parent package
pep-0328でパッケージの完全なレプリカを作りました。
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
subpackage2/
__init__.py
moduleZ.py
moduleA.py
インポートはコンソールから行いました。
spamとeggsという名前の関数をそれぞれの適切なモジュールで作りました。 当然ながら、うまくいきませんでした。 答えは4番目に挙げたURLにあるらしいのですが、私にとっては全て同窓会です。私が訪れたURLの1つにこんな回答がありました。
相対インポートでは、モジュールの name 属性を使用して、パッケージ階層におけるそのモジュールの位置を決定します。もしモジュールの名前がパッケージ情報を含んでいなければ (例えば 'main' に設定されていれば)、 モジュールがファイルシステム上のどこに実際に配置されているかに関わらず、 モジュールがトップレベルモジュールであるかのように相対インポートが解決されます。
上記の回答は期待できそうですが、私には全て象形文字にしか見えません。 どうすれば Python が "Attempted relative import in non-package" を返さないようにできるかという私の質問には、おそらく -m を含む答えがあるはずです。
なぜPythonはそのようなエラーメッセージを出すのか、"non-package"の意味は何か、なぜ、どのように「パッケージ」を定義するのか、誰か教えてくれませんか? 幼稚園児でもわかるような簡単な言葉で的確な回答を .
解き方は?
スクリプトとモジュールの比較
ここで説明します。 簡単に言うと、Pythonのファイルを直接実行するのと、どこかからそのファイルをインポートするのとでは、大きな違いがあるということです。 ファイルがどのディレクトリにあるか知っているだけでは、Pythonがそのファイルをどのパッケージにあると考えるかは決まりません。 さらに、ファイルをどのようにPythonに読み込むか(実行するかインポートするか)にも依存します。
Pythonファイルをロードする方法には、トップレベルのスクリプトとしてロードする方法、または
モジュールになります。 ファイルを直接実行する場合、トップレベルのスクリプトとしてロードされます。
python myfile.py
をコマンドラインで入力します。 モジュールとして読み込まれるのは
import
ステートメントが他のファイル内で遭遇した場合。 トップレベルのスクリプトは同時に1つしか存在できません。トップレベルのスクリプトは、物事を始めるために実行した Python ファイルです。
ネーミング
ファイルが読み込まれるとき、そのファイルには名前が付けられます。
__name__
属性があります)。 トップレベルのスクリプトとしてロードされた場合、その名前は
__main__
. モジュールとしてロードされた場合、その名前はファイル名の前に、その一部が含まれるパッケージ/サブパッケージの名前をドットで区切ったものになります。
だから例えばあなたの例では
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleA.py
をインポートした場合
moduleX
(注
インポート
という名前になります。
package.subpackage1.moduleX
. をインポートした場合
moduleA
で、その名前は
package.moduleA
. しかし、もし
を直接実行します。
moduleX
をコマンドラインから実行すると、その名前は代わりに
__main__
を直接実行すると
moduleA
という名前になります。
__main__
. モジュールがトップレベルのスクリプトとして実行されると、通常の名前はなくなり、代わりに
__main__
.
含むパッケージを通してモジュールのNOTにアクセスする
モジュールの名前は、それがディレクトリから "直接"インポートされたか、パッケージを経由してインポートされたかによって異なります。 これは、あるディレクトリで Python を実行し、その同じディレクトリ(またはそのサブディレクトリ)にあるファイルをインポートしようとした場合にのみ、違いが生じます。 例えば、Pythonインタプリタをディレクトリ
package/subpackage1
を実行します。
import moduleX
の名前は
moduleX
は、単に
moduleX
であり
package.subpackage1.moduleX
. これは、インタプリタが対話的に入力されたときに、Python が現在のディレクトリを検索パスに追加するからです。もし、インポートするモジュールを現在のディレクトリで見つけた場合、そのディレクトリがパッケージの一部であることを知らず、パッケージ情報がモジュール名の一部とならないからです。
特殊なケースとして、インタプリタを対話的に実行した場合(例えば、単に
python
で、その場でPythonコードの入力を開始します)。 この場合、その対話型セッションの名前は
__main__
.
さて、ここからがエラーメッセージの重要なポイントです。 モジュール名にドットがない場合、それはパッケージの一部とはみなされません。 . 実際にファイルがディスク上のどこにあるかは関係ありません。 重要なのはその名前が何であるかということであり、その名前はあなたがそれをどのように読み込んだかに依存するのです。
では、質問に含まれる引用文を見てください。
<ブロッククオート相対インポートでは、モジュールの name 属性を使用して、パッケージ階層におけるそのモジュールの位置を決定します。もしモジュールの名前がパッケージ情報を含んでいなければ (例えば 'main' に設定されていれば)、 モジュールがファイルシステム上のどこに実際に位置しているかに関わらず、 モジュールがトップレベルモジュールであるかのように相対インポートが解決されます。
相対インポート...
相対インポートでは、モジュールの
名前
を使用して、パッケージ内の位置を決定します。 のような相対インポートを使用する場合
from .. import foo
このドットは、パッケージの階層を何段階か上に移動することを意味します。 たとえば、現在のモジュールの名前が
package.subpackage1.moduleX
であれば
..moduleA
という意味になります。
package.moduleA
. の場合は
from .. import
が動作するためには、モジュール名には少なくとも
import
ステートメントを使用します。
... は、パッケージの中で相対的なものでしかありません
しかし、モジュール名が
__main__
の場合、パッケージに含まれるとはみなされません。 その名前にはドットがありません。
from .. import
ステートメントを含むことができます。 これを実行しようとすると、"relative-import in non-package" というエラーが発生します。
スクリプトは相対的なインポートができません
おそらくあなたがしたことは
moduleX
などをコマンドラインから実行します。 その際、その名前が
__main__
これは、その名前からパッケージに含まれていることが分からないため、その中での相対インポートに失敗することを意味します。これは、モジュールがあるのと同じディレクトリから Python を実行し、そのモジュールをインポートしようとした場合にも起こることであることに注意してください。
また、対話型インタープリターを実行するとき、その対話型セッションの "name"は常に
__main__
. したがって
対話型セッションから直接相対インポートを行うことはできません。
. 相対インポートは、モジュールファイル内でのみ使用可能です。
2つの解決策
-
本当に実行したい場合は
moduleX
を直接使用したいが、パッケージの一部と見なされるようにしたい場合、次のようにします。python -m package.subpackage1.moduleX
. その-m
はPythonにトップレベルのスクリプトとしてではなく、モジュールとしてロードするように指示します。 -
あるいは、実際には 実行
moduleX
のように、他のスクリプトを実行したいだけなら、次のようにします。myfile.py
は、その が使用します。 の中にある関数moduleX
. そのような場合はmyfile.py
他の場所 - ない の中にあるpackage
ディレクトリに移動して実行します。 もしmyfile.py
のようなことをするとfrom package.moduleA import spam
であれば、問題なく動作します。
備考
-
これらのソリューションのいずれにおいても、パッケージ・ディレクトリ (
package
は、Pythonモジュールの検索パス(sys.path
). そうでない場合は、パッケージの中の何かを確実に使用することは全くできません。 -
Python 2.6 からは、パッケージ解決のためのモジュールの "name" は、その
__name__
属性だけでなく__package__
属性があります。 そのため、明示的なシンボルである__name__
を使用して、モジュールの "name" を参照します。 Python 2.6 からはモジュールの "name" は事実上__package__ + '.' + __name__
または、単に__name__
もし__package__
はNone
.)
関連
-
[解決済み】お使いのCPUは、このTensorFlowバイナリが使用するようにコンパイルされていない命令をサポートしています。AVX AVX2
-
[解決済み] builtins.TypeError: strでなければならない、bytesではない
-
[解決済み】"No JSON object could be decoded "よりも良いエラーメッセージを表示する。
-
[解決済み] for'ループでインデックスにアクセスする?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] __init__.py は何のためにあるのですか?
-
[解決済み] MySQLでコマンドラインを使用してSQLファイルをインポートするにはどうすればよいですか?
-
[解決済み] Pythonで相対インポートを行うには?
-
[解決済み】forループを使った辞書の反復処理
-
[解決済み】Python 3での相対インポート
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python カメの描画コマンドとその例
-
python implement mysql add delete check change サンプルコード
-
Python LeNetネットワークの説明とpytorchでの実装
-
[解決済み】お使いのCPUは、このTensorFlowバイナリが使用するようにコンパイルされていない命令をサポートしています。AVX AVX2
-
[解決済み】RuntimeWarning: 割り算で無効な値が発生しました。
-
[解決済み】なぜ「LinAlgError: Grangercausalitytestsから「Singular matrix」と表示されるのはなぜですか?
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み】Python Error: "ValueError: need more than 1 value to unpack" (バリューエラー:解凍に1つ以上の値が必要です
-
[解決済み】ImportError: bs4という名前のモジュールがない(BeautifulSoup)
-
[解決済み] pythonの相対的なインポートを説明できる人はいますか?[重複している]。