はじめに
Python でモジュールを整理するには 2 つの方法があり、1 つは単純な Python ファイルであり、もう 1 つはパッケージであり、複数の Python ファイルが含まれている必要があります。 __init__.py というファイルがあるため、ディレクトリ名がモジュール名になり、パッケージ内の Python ファイルもパッケージ名を使用してインポートできます
インポート構文
インポート構文には 2 種類あります。
1. モジュールを直接インポートします
import Module import Module as xx
2. モジュール(下位レベルのモジュール、クラス、関数、変数など)からオブジェクトをインポートします
from Module import Name from Module immport Name as yy
の構文は、オブジェクトのエイリアスを設定するために使用されます(ここでのオブジェクトはモジュール、クラス、関数などを指します)、オブジェクトをインポートします。名前は現在のファイルの名前空間を導入します
次のディレクトリ構造があると仮定します
├── A.py └── pkg ├── B.py └── __init__.py
現在のディレクトリには、次のステートメントは有効です
import A import pkg import pkg.B from pkg import B
説明を簡単にするために、以下に構文の例はありません
インポート手順
Python でロードされたすべてのモジュール情報は、インポート時に sys.modules 構造に保存されます。モジュールをインポートする場合、次の手順が実行されます
Aをインポートする場合は、sys.modulesにすでにAがあるかどうかを確認し、存在しない場合はロードされません。 A
AインポートBからの場合、最初にAのモジュールオブジェクトを作成し、次にAを解析し、そこからBを見つけてAの__dict__に入力します
ネストされたインポート
モジュールをインポートするとき、次のことを心配するかもしれませんモジュールが複数回インポートされるとします。 A、B、C という 3 つのモジュールがあるとします。 A は B と C をインポートする必要があり、B は C をインポートする必要があります。そのため、A は import C を 2 回実行し、1 回は自分自身のインポート用に実行します。ただし、上記のインポート手順によると、2回目のインポート時にモジュールがロードされていることがわかり、インポートは繰り返されます
が、エラーが発生します以下の状況で報告されます
#filename: A.py from B import BB class AA:pass #filename: B.py from A import AA class BB:pass
この時、A.pyを実行してもB.pyを実行してもImportError例外がスローされます。理由は以下の通りです
。ファイル A.py が B import BB から実行され、B.py が最初にスキャンされ、A の名前空間に B のモジュール オブジェクトが作成され、B から BB を見つけようとします
B.py の最初の行をスキャンして、実行 from A import AA 、このとき A.py をスキャンします
A.py の 1 行目をスキャンして B から実行 import BB 手順 1 で B のモジュール オブジェクトが作成されているため、BB が直接取得されます。 B のモジュール オブジェクトの __dict__ から、明らかに BB を取得できないため、例外がスローされます
A.py または B.py の 2 行のコードを交換します
単一のファイルをインポートする場合、ファイル内のクラス、関数、変数はすべてインポート オブジェクトとして使用できます。 パッケージをインポートする場合、サブパッケージ、パッケージ内のファイル、および __init__ のクラス、関数、変数をインポート オブジェクトとして使用できます。 .pyは全てインポートオブジェクトとして利用可能です以下のようなディレクトリ構造があるとします
pkg ├── __init__.py └── file.py
argument = 0 class A:pass
>>> import pkg >>> import pkg.file >>> from pkg import file >>> from pkg import A >>> from pkg import argument
>>> import pkg.A >>> import pkg.argument
app ├── __inti__.py ├── mod1 │ ├── file1.py │ └── __init__.py ├── mod2 │ ├── file2.py │ └── __init__.py └── start.py
A ├── B1 │ ├── C1 │ │ └── file.py │ └── C2 └── B2
其中A,B1,B2,C1,C2都为包,这里为了展示简单没有列出__init__.py文件,当file.py的包结构为A.B1.C1.file(注意,是根据__name__来的,而不是磁盘的目录结构,在不同目录下执行file.py时对应的包目录结构都是不一样的)时,在file.py中可采用如下的绝对的导入
import A.B1.C2 import A.B2
和如下的相对导入
from .. import C2 from ... import B2
什么情况下会让file.py的包结构为A.B1.C1.file呢,有如下两种
在A的上层目录执行python -m A.B1.C1.file, 此时明确指定了包结构
在A的上层目录建立文件start.py,在start.py里有import A.B1.C1.file,然后执行python start.py,此时包结构是根据file.py的__name__变量来的
再看前面出错的两种情况,第一种执行python file1.py和python mod1/file1.py,此时file.py的__name__为__main__ ,也就是说它本身就是顶层模块,并没有包结构,所以会报错
第二种情况,在执行python -m mod1.file1和python start.py时,前者明确告诉解释器mod1是顶层模块,后者需要导入file1,而file1.py的__name__为mod1.file1,顶层模块为也mod1,所以在file1.py中执行from ..mod2 import file2时会报错 ,因为mod2并不在顶层模块mod1内部。通过错误堆栈可以看出,并不是在start.py中绝对导入时报错,而是在file1.py中相对导入报的错
那么如何才能偶正确执行呢,有两种方法,一种是在app上层目录执行python -m app.mod1.file1,另一种是改变目录结构,将所有包放在一个大包中,如下
app ├── pkg │ ├── __init__.py │ ├── mod1 │ │ ├── __init__.py │ │ └── file1.py │ └── mod2 │ ├── __init__.py │ └── file2.py └── start.py
start.py内容改成import pkg.mod1.file1,然后在app下执行python start.py
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用python能带来一定的帮助,如有疑问大家可以留言交流。
更多python中import学习备忘笔记相关文章请关注PHP中文网!