python tips(3);import的机制

  1.标准的import

      python中,所有加载到内存中的模块都是放在sys.modules中,当import一个模块的时候,会在这个列表中查看是否加载了这个模块,如果加载了,则只是将模块名字加入到正在调用import的模块的Local空间。如果没有加载,则从sys.path中按照模块名称查找,模块可以是py,pyc,pyd,找到后将模块载入内存,并加到 sys.modules 中,并将名称导入到当前的 Local 名字空间。

一个模块不会重复载入。多个不同的模块都可以用 import 引入同一个模块到自己的 Local 名字空间,其实背后的 PyModuleObject 对象只有一个。这里说一个容易忽略的问题:import 只能导入模块,不能导入模块中的对象(类、函数、变量等)。例如:模块 A(A.py)中有个函数 getName,另一个模块不能通过 import A.getName 将 getName导入到本模块,只能用 from A import getName。

  2.嵌套的import

例如:

文件[A.py]

?


1

2

from B import D

class C:pass

文件[ B.py ]

?


1

2

from A import C

class D:pass

为什么执行 A 的时候不能加载 D 呢?
如果将 A.py 改为:import B 就可以了。
这是怎么回事呢?

RobertChen:这跟Python内部 import 的机制是有关的,具体到 from B import D,Python 内部会分成几个步骤:
(1)在 sys.modules 中查找符号 “B”
(2)如果符号 B 存在,则获得符号 B 对应的 module 对象。
  从 <modult B> 的 __dict__ 中获得符号 “D” 对应的对象,如果 “D” 不存在,则抛出异常。
(3)如果符号 B 不存在,则创建一个新的 module 对象 <module B>,注意,此时,module 对象的 __dict__ 为空。
执行 B.py 中的表达式,填充 <module B> 的 __dict__。
从  <module B> 的 __dict__ 中获得 “D” 对应的对象,如果 “D” 不存在,则抛出异常。

所以这个例子的执行顺序如下:

1、执行 A.py 中的 from B import D 由于是执行的 python A.py,所以在 sys.modules 中并没有 <module B> 存在, 首先为 B.py 创建一个 module 对象 (<module B>) , 注意,这时创建的这个 module 对象是空的,里边啥也没有, 在 Python 内部创建了这个 module 对象之后,就会解析执行 B.py,其目的是填充 <module B> 这个 __dict__。 
2、执行 B.py中的from A import C 在执行B.py的过程中,会碰到这一句, 首先检查sys.modules这个module缓存中是否已经存在<module A>了, 由于这时缓存还没有缓存<module A>, 所以类似的,Python内部会为A.py创建一个module对象(<module A>), 然后,同样地,执行A.py中的语句
3、再次执行A.py中的from B import D 这时,由于在第1步时,创建的<module B>对象已经缓存在了sys.modules中, 所以直接就得到了<module B>, 但是,注意,从整个过程来看,我们知道,这时<module B>还是一个空的对象,里面啥也没有, 所以从这个module中获得符号"D"的操作就会抛出异常。 如果这里只是import B,由于"B"这个符号在sys.modules中已经存在,所以是不会抛出异常的。

时间: 2024-11-08 22:23:03

python tips(3);import的机制的相关文章

python中import的机制与实现

原文出处: 刘畅(@你猜我猜不猜猜你是谁) 概述 Python 是一门优美简单.功能强大的动态语言.在刚刚接触这门语言时,我们会被其优美的格式.简洁的语法和无穷无尽的类库所震撼.在真正的将python应用到实际的项目中,你会遇到一些无法避免的问题.最让人困惑不解的问题有二类,一个 编码问题,另一个则是引用问题. 本文主要讨论关于Python中import的机制与实现.以及介绍一些有意思的Python Hooks. Python 类库引入机制 首先,看一个简单的例子: """

[Python Tips]如何找出Python list中有重复的项

如果一个Python list中有很多重复的项,如何有效地找到多少重复的项呢? 可以使用collection的Counter方法.. >>> from collections import Counter >>> Counter([11,22,11,44,22,33]) Counter({11: 2, 22: 2, 33: 1, 44: 1}) [Python Tips]如何找出Python list中有重复的项,布布扣,bubuko.com

python tips(持续更新)

1. 引用上一层目录 import syssys.path.append('..')import xx 2. python json JSON是一种轻量级的数据交换格式.可以解决数据库中文存储问题,对象序列化问题,等等. import json encodedjson = json.dumps(obj) decodejson = json.loads(encodedjson) 非常简单. 3. 静态方法 在函数前面@staticmethod @staticmethod def func(): p

[转]30 ESSENTIAL PYTHON TIPS AND TRICKS FOR PROGRAMMERS

If you ask any Python programmer to tell about the strengths of Python, he will quote brevity and high readability as the most influencing ones. In this Python tutorial, we’ll cover many essential Python tips and tricks that will authenticate the abo

python变量存储的缓存机制

python变量存储的缓存机制 1.  在同一文件(模块)里 1.对于整型而言,-5~正无穷范围内的相同值 id一致 2.对于浮点数而言,非负数范围内的相同值 id一致 3.布尔值而言,值相同情况下,id一致 4.复数的id标识都不相同(在 实数+虚数 这样的结构中) 5.字符串而言,字符串值相同情况下,id一致 6.列表,元组,字典,集合无论什么情况 id标识都不同(但空元组的id标识一样) 2.  不同文件(模块)里,部分数据驻留小数据池中 python提前在内存中创建了-5~256 范围的

Python TIPS

枚举 之前我们这样操作: Python 1 2 3 4 i = 0 for item in iterable: print i, item i += 1 现在我们这样操作: Python 1 2 for i, item in enumerate(iterable): print i, item enumerate函数还可以接收第二个参数.就像下面这样: Python 1 2 3 4 5 >>> list(enumerate('abc')) [(0, 'a'), (1, 'b'), (2,

Python中的import和from import

一.Python路径介绍 在python用import或者from...import来导入相应的模块. 模块其实就是一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模块导入到我们的程序中,我们就可以使用了. 这类似于C语言中的include头文件,Python中我们用import导入我们需要的模块. 二.搜索路径 Python会在以下路径中搜索它想要寻找的模块: 1. 程序所在的文件夹 2. 标准库的安装路径 3. 操作系统环境变量PYTHONPATH所

python之禅 --- import this

>>> import thisThe Zen of Python, by Tim Peters Beautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability cou

python中的import,reload,以及__import__

import作用:导入/引入一个python标准模块,其中包括.py文件.带有__init__.py文件的目录.e.g: [python] view plaincopy import module_name[,module1,...] from module import *|child[,child1,...] 说明:多次重复使用import语句时,不会重新加载被指定的模块,只是把对该模块的内存地址给引用到本地变量环境.测试: [python] view plaincopy a.py #!/u