こんにちは、私はsomenzzです。鄭兄弟と呼んでください。
Python のインポートは非常に直感的ですが、それでも、パッケージがそこにあるにもかかわらず、ModuleNotFoundError が発生することがあります。相対パスが非常に正しい場合でも、エラーが報告されます
ImportError: attempted relative import with no known parent package
同じディレクトリにあるモジュールをインポートするのと、別のディレクトリにあるモジュールをインポートするのはまったく異なります。この記事では、インポートを簡単に処理できるように、インポートを使用するときによく発生するいくつかの問題を分析します。これに基づいて、独自のパッケージを簡単に作成できます。
モジュールとパッケージの関係はファイルに例えられます。モジュール ファイルのみ。
Python ドキュメントで説明されているように、Python ファイルはモジュールであり、Python ファイル名 (拡張子 .py を除く) がモジュール名です。
モジュールには、モジュールによって定義された名前空間の一部である変数、関数、クラスを含めることができます。そのため、2 つの異なるモジュールが同じ変数、関数、クラスを持つことができるため、変数の名前付けは問題になりません。名前。 。
モジュールとパッケージの関係は、ファイルとディレクトリにたとえることができます。パッケージはディレクトリです。
パッケージにはモジュールまたはサブパッケージを含めることができます。モジュールは、変数、関数、クラスが 2 つの異なるモジュールで同じ名前を持つことができるように、名前空間を定義します。同様に、パッケージは、そのコンポーネント パッケージとモジュールに対して同じことを行います。メイン パッケージには、ドットを介してアクセスできます。モジュールとパッケージの。
基本パッケージには、サブパッケージ、モジュール、__init__.py (Python 3.3 以降は不要)、setup.py を含めることができます。考えられるパッケージ構造は次のようになります。
そして、setup.py はパッケージが配置されているホーム ディレクトリに存在し、必要な依存関係、スクリプト、サブパッケージなどの構成情報が含まれています。パッケージの名前、作成者、説明など、パッケージに関するメタデータを指定することもできます。
setup.py は、pip がパッケージをインストールするために使用するファイルです。
まず簡単な例を見てみましょう。たとえば、同じディレクトリに 2 つのファイル file1.py と file2.py があります。内容は非常に単純です。それぞれのファイル名の違いは、file1 が file2.py にインポートされることです。
#file1.py print("This is file1.py") #file2.py print("This is file2.py") import file1
file2.py を実行すると、次の結果が得られます。
❯ python file2.py This is file2.py This is file1.py
参照:
インポートの検索順序も知る必要があります。覚えておく必要があることは 1 つだけです。インポートは sys.path 内を検索するということです。
たとえば、file2.py の最後にコード行 import sys; print(sys.path) を追加すると、インポートの検索パスを出力できます。
# sys.path の順序がわかります:
実行スクリプトが配置されているパスが最初に検索されます
インタープリタ環境では、sys.path[0 ] は、インタープリタが開始されるパスです。''
あるモジュールが別のモジュールをインポートし、さらにそのモジュールが別のモジュールをインポートする場合、最初のモジュールの sys.path が、インタープリタが 2 番目のモジュールを検索する場所になります。インポートステートメント。
import aa import aa.bb from aa import bb
from . import aa from .aa import bb from .. import yy
file3.py :
print("This is file3.py")
from . import file3 print("This is file4.py")
只要我们直接运行 file4.py,那是一定会报错的:
Python 提示我们:
ImportError: attempted relative import with no known parent package
也就是说相对导入不知道父包是谁,换句话说,这是一个子包,必须让父包来调用它,直接运行这个文件是不行的,即使你在 file4.py 的目录 subpackage1 同级的目录执行该文件也是不行的,见上图。
但是在 file4.py 的目录 subpackage1 同级的目录作为一个 module 来执行是可以的,如下图:
换句话说,我们把 subpackage1 作为一个包来让别人用,相对导入是可以的,比如说我们在目录 subpackage1 同级的目录新建一个 file5.py 的文件,内容如下:
file5.py:
from subpackage1 import file4。
然后,执行 python file5.py 可以看出,相对导入已经正常工作:
结论
先上一个图来看下目录及引用结构,方块的是目录,椭圆的是文件,曲线是引用:
其中 import_example 目录下有 setup.py 和 run.py
run.py 导入了 file4、file5、file6。
file4 导入了 file3,file5 导入了 file3。
file6 导入了 file2,file2 导入了 file1。
现在我们来执行一下 run.py 看下效果:
可以看出所有相对导入都已正常工作,虽然 file3 被导入了两次,但只执行了一次,说明 Python 内部已经考虑了同一个包的多重导入问题。
自定义包就是让其他文件导入使用的,因此 pythonimportexample目录下都使用相对导入,源代码见:
https://gitee.com/somenzz/code-example/tree/master/import_example
点阅读原文也可以直接访问。
这里还有一些自定义包的例子:
本文分享了什么是模块(module),什么是包(package),import 的搜索路径,也分享了相对导入和绝对导入的区别,最后举了一个非常实用的 import 例子,方便你构建自己的包。
以上がPython のインポートはどのように機能するのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。