深入解析Python的import机制:从sys.modules到Local名字空间的全面指南

本文详细介绍了Python的进口机制,这对于理解Python的运行机制非常有帮助!

深入解析Python的import机制:从sys.modules到Local名字空间的全面指南

1。标准导入:

将python中的所有模块都放在sys.modules中。导入模块时,首先在此列表中检查是否已加载模块。如果加载,它只会将模块的名称添加到调用导入的模块的本地名称空间中。如果未加载,请根据SYS.Path目录中的模块名称查找模块文件。该模块可以是PY,PYC,PYD。找到它后,将模块加载到内存中,将其添加到SYS.MODULES,然后将名称导入当前本地名称空间。

模块不会重复加载。多个不同的模块可以使用导入将同一模块导入其本地名称空间。实际上,其背后只有一个pymoduleObject对象。这是一个容易忽略的问题:导入只能导入模块,但不能在模块中导入对象(类,功能,变量等)。例如:模块A(a.py)中有一个函数getName,另一个模块无法通过import a.getName将getName入用到此模块中,因此您只能从import getName中使用。

2.持续的导入:

1)顺序嵌套:此模块导入模块A(导入A),在A中,它导入B,并且模块B可以导入其他模块...

筑巢更容易理解。要注意的一件事是,每个模块的本地名称空间是独立的。对于上述示例,导入A后,此模块只能访问模块A,但无法访问模块B和其他模块。尽管已将模块B加载到内存中,如果访问,则必须在此模块中明确导入B。

2)例如筑巢:

文件[a.py]

从B进口D

C级:通过

文件[B.Py]

从进口c

D级:通过

为什么执行A时不能加载D?

如果将A.Py更改为:导入B,那很好。

这是怎么回事?

罗伯钦(Robertchen):这与Python的进口机理有关。具体而言,从b进口D中,Python将分为几个步骤:

(1)在sys.modules中找到符号“ b”

(2)如果存在符号B,则获得与符号B相对应的模块对象。

获取与__ -dict__符号“ D”相对应的对象,如果不存在“ D”,则会引发异常。

(3)如果符号B不存在,则会创建一个新的模块对象。请注意,此时,模块对象的__ -dict__是空的。

在b.py中执行表达式,填写___dict__。

从“ __ -dict__”的“ D”中获取对应的对象,如果不存在“ D”,则会引发异常。

因此,此示例的执行顺序如下:

1。从a.py中的B导入d执行。由于它被执行python a.py,因此在sys.modules中不存在。首先,为B.Py创建一个模块对象()。请注意,此时创建的模块对象是空的,内部没有任何东西。在Python中创建此模块对象后,将对B.Py进行解析和执行,目的是填充此__Dict__。

2。从b.py的导入c执行执行B.Py时,您会遇到此句子。首先检查sys.modules的模块缓存。由于此时尚未缓存缓存,因此Python为A.Py创建一个模块对象(),然后同样,在A.Py中执行语句

3。再次在A.Py中从B导入d执行。目前,由于创建的对象已在步骤1中被缓存在Sys.Modules中,因此我直接得到了它。但是,请注意,从整个过程中,我都可以看一下。 ,我们知道目前它仍然是一个没有内部的空对象,因此从该模块中获取符号“ D”的操作将引发例外。如果这只是导入b,则由于符号“ b”已经存在于sys.modules中,因此不会抛出任何例外。

ZQ:插图如下:

3。只要在软件包导入的文件夹下有一个__init__.py文件,就可以将此文件夹视为包装。导入软件包的过程基本上与模块的过程相同。但是,在导入软件包时,将执行软件包目录中的__init__.py,而不是模块中的语句。此外,如果您只是简单地导入软件包,并且在软件包__init__.py中没有其他明确的初始化操作,则该软件包下面的模块将不会自动导入。

例如:

有以下软件包结构:

PA

| ----- __init__.py

| ----波

| ----- PB1

| ----- __init__.py

| ------ PB1_M.PY

| ----- PB2

| ----- __init__.py

| ------ PB2_M.Py

有以下程序:

导入系统

导入pa。波#1

导入PA.PB1#2

导入pa.pb1.pb1_m作为m1#3

导入pa.pb2.pb2_m#4

pa.wave.getName()#5

m1.getName()#6

pa.pb.pb2_m.getName()#7

1)执行#1后,SYS.Modules将具有PA和PA.Wave模块。目前,可以调用PA.波的任何类或功能。但是,在PA.pb1(2)下没有模块。目前,本地有一个PA名。

2)执行#2后,只需将pa.pb1加载到内存中即可。 Sys.Modules,Pa.Wave和PA.PB1中将有三个模块,但是在PA.PB1下没有模块自动加载到存储器中。 ,如果直接执行pa.pb1.pb1_m.getName(),则会发生错误,因为pa.pb1中没有pb1_m。当前,本地只有PA名,并且没有PA.PB1名称。

3)执行#3后,将PA.PB1下的PB1_M加载到内存中。 Sys.Modules中将有四个模块:PA,PA.Wave,Pa.pb1和Pa.pb1.pb1_m。 PA目前可以执行。 .pb1.pb1_m.getName()在这里。由于所使用的是,除了PA名之外,还将M1作为PA.pb1.pb1.m在当前本地中的别名。

4)执行#4之后,PA.PB2,PA.PB2.PB2_M将加载到内存中。将有PA,PA.Wave,PA.PB1,PA.PB1.PB1_M,PA.PB2和SYS.Modules中的PA。 .pb2.pb2_m六个模块。目前,本地只有PA和M1。

下面的#5,#6和#7都可以正确运行。

请注意,如果pa.pb2.pb2_m想要导入pa.pb1.pb1_m和pa.wave,它可以直接成功。最好使用清晰的导入路径,对于./的相对导入路径不建议使用。

你可能想看:
« 上一篇
下一篇 »

相关推荐

python爬虫教程PDF,Python爬虫书PDF

2026年09月02日

32阅读

外国教程python,python编程教学视频

2026年09月02日

27阅读

python简明教程沈洁元,python详细基础教程

2026年09月02日

21阅读

python库包教程,python 包

2026年09月02日

27阅读

python教程大全集,python教程600集

2026年09月02日

27阅读

python入门教程完整版,python零基础入门全套教程视频

2026年09月02日

23阅读