`
com1com4
  • 浏览: 162208 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

[转]Python Import机制

阅读更多

模块的搜索路径

模块的搜索路径都放在了sys.path列表中,如果缺省的sys.path中没有含有自己的模块或包的路径,可以动态的加入 (sys.path.apend)即可。下面是sys.path在Windows平台下的添加规则。

1、sys.path第一个路径往往是主模块所在的目录。在交互环境下添加一个空项,它对应当前目录。

2、如果PYTHONPATH环境变量存在,sys.path会加载此变量指定的目录。

3、我们尝试找到Python Home,如果设置了PYTHONHOME环境变量,我们认为这就是Python Home,否则,我们使用python.exe所在目录找到lib\os.py去推断Python Home。

如果我们确实找到了Python Home,则相关的子目录(Lib、plat-win、lib-tk等)将以Python Home为基础加入到sys.path,并导入(执行)lib/site.py,将site-specific目录及其下的包加入。

如果我们没有找到Python Home,则把注册表Software\Python\PythonCore\2.5\PythonPath的项加入sys.path(HKLM和 HKCU合并后加入),但相关的子目录不会自动添加的。

4、如果我们没有找到Python Home,并且没有PYTHONPATH环境变量,并且不能在注册表中找到PythonPath,那么缺省相对路径将加入(如:.\Lib;. \plat-win等)。

 

总结如下:

当在安装好的主目录中运行Python.exe时,首先推断Python Home,如果找到了PythonHome,注册表中的PythonPath将被忽略;否则将注册表的PythonPath加入。

如果PYTHONPATH环境变量存在,sys.path肯定会加载此变量指定的目录。

如果Python.exe在另外的一个目录下(不同的目录,比如通过COM嵌入到其他程序),Python Home将不推断,此时注册表的PythonPath将被使用。

如果Python.exe不能发现他的主目录(PythonHome),并且注册表也没有PythonPath,则将加入缺省的相对目录。

 

标准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导入到本模块,只能用import A。如果想只导入特定的类、函数、变量则用from A import getName即可。

 

嵌套Import

嵌套import,我分两种情况,一种是:本模块导入A模块(import A),而A中又有import语句,会激活另一个import动作,如import B,而B模块又可以import其他模块,一直下去。

 

对这种嵌套比较容易理解,注意一点就是各个模块的Local名字空间是独立的,所以上面的例子,本模块import A完了后本模块只能访问模块A,不能访问B及其他模块。虽然模块B已经加载到内存了,如果要访问还要在明确的在本模块中import B。

 

另外一种嵌套指,在模块A中import B,而在模块B中import A。这时会怎么样呢?这个在Python列表中由RobertChen给出了详细解释,抄录如下:

[A.py]
from B import D
class C:pass

[B.py]
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对象<module B>。

    从<module 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中已经存在,所以是不会抛出异常的。

 

上面的解释已经由Zoom.Quiet收录在啄木鸟 了,里面有图,可以参考一下。

Package(包) Import

包(Package)可以看成模块的集合,只要一个文件夹下面有个__init__.py文件,那么这个文件夹就可以看做是一个包。包下面的文件夹 还可以成为包(子包)。更进一步,多个较小的包可以聚合成一个较大的包,通过包这种结构,方便了类的管理和维护,也方便了用户的使用。比如 SQLAlchemy等都是以包的形式发布给用户的。

 

包和模块其实是很类似的东西,如果查看包的类型import SQLAlchemy type(SQLAlchemy),可以看到其实也是<type 'module'>。import包的时候查找的路径也是sys.path。

 

包导入的过程和模块的基本一致,只是导入包的时候会执行此包目录下的__init__.py 而不是模块里面的语 句了。另外,如果只是单纯的导入包,而包的__init__.py中又没有明确的其他初始化操作,那么此包下面的模块是不会自动导入的。如:

PA

--__init__.py

--wave.py

--PB1

  --__init__.py

  --pb1_m.py

--PB2

  --__init__.py

  --pb2_m.py

__init__.py都为空,如果有以下程序:

  1. import sys
  2. import PA.wave #1
  3. import PA.PB1 #2
  4. import PA.PB1.pb1_m as m1 #3
  5. import PA.PB2.pb2_m #4
  6. PA.wave.getName() #5
  7. m1.getName() #6

  8. PA.PB2.pb2_m.getName() #7

 

当执行#1后,sys.modules会同时存在PA、PA.wave两个模块,此时可以调用PA.wave的任何类或函数了。但不能调用 PA.PB1(2)下的任何模块。当前Local中有了PA名字。

 

当执行#2后,只是将PA.PB1载入内存,sys.modules中会有PA、PA.wave、PA.PB1三个模块,但是PA.PB1下的任何 模块都没有自动载入内存,此时如果直接执行PA.PB1.pb1_m.getName()则会出错,因为PA.PB1中并没有pb1_m。当前Local 中还是只有PA名字,并没有PA.PB1名字。

 

当执行#3后,会将PA.PB1下的pb1_m载入内存,sys.modules中会有PA、PA.wave、PA.PB1、 PA.PB1.pb1_m四

个模块,此时可以执行PA.PB1.pb1_m.getName()了。由于使用了as,当前Local中除了PA名字,另外 添加了m1作为PA.PB1.pb1_m的别名。

 

当执行#4后,会将PA.PB2、PA.PB2.pb2_m载入内存,sys.modules中会有PA、PA.wave、PA.PB1、 PA.PB1.pb1_m、PA.PB2、PA.PB2.pb2_m六个模块。当前Local中还是只有PA、m1。

 

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

 

注意的是:如果PA.PB2.pb2_m想导入PA.PB1.pb1_m、PA.wave是可以直接成功的。最好是采用明确的导入路径,对 于./..相对导入路径还是不推荐用。

分享到:
评论

相关推荐

    python import机制 - .pptx

    讲解了python的import机制,从pyc与py区别,python词法分析,import种类等方面分析python的import

    python import

    在Python编程中,`import`语句是用于引入其他模块或包的关键字,这使得代码可以复用和组织。当你需要在不同的文件夹结构中导入`.py`文件时,了解正确的导入策略至关重要。以下是一些关于如何在Python中正确导入跨...

    python import搜索路径与重新导入

    Python Import 搜索路径与重新导入机制 Python 是一种流行的编程语言,它提供了丰富的模块和函数来帮助开发者快速开发应用程序。其中,Import 机制是 Python 中非常重要的一部分,它允许开发者导入其他模块并使用...

    java2python--java代码转python工具

    8. 引用和导入:Java的包和类引用需转换为Python的模块导入机制,例如import语句。 9. 多线程:Java的多线程模型(Thread类)与Python的多线程(threading模块)有差异,转换时需要考虑线程安全和并发控制。 10. ...

    详解Python中import机制

    ### 详解Python中import机制 #### 一、Python导入机制概览 在Python编程中,模块(module)和包(package)是管理代码的核心组成部分。它们不仅有助于代码的组织,还便于复用和维护。本篇文章将深入探讨Python中`...

    python之import机制详解

    本文详述了Python的import机制,对于理解Python的运行机制很有帮助! 1.标准import: Python中所有加载到内存的模块都放在 sys.modules 。当 import 一个模块时首先会在这个列表中查找是否已经加载了此模块,如果...

    python import机制深入研究

    Python的`import`机制是其核心特性之一,它允许我们重用代码并组织复杂的项目结构。深入理解这一机制对于编写可维护的Python程序至关重要。在本文中,我们将探讨`import`语句的工作原理,特别是涉及相对导入和`sys....

    python 全局变量的import机制介绍

    ### Python全局变量的Import机制详解 #### 背景与目的 在Python的学习过程中,特别是在探索设计模式的应用,比如工厂模式的实践中,我们可能会遇到如何使用全局变量来模拟C++中宏的功能,以便实现服务的自动注册。...

    Python 中的 import 机制之实现远程导入模块

    在 Python 中使用 import 关键字来实现这个操作,但不是唯一的方法,还有 importlib.import_module() 和 __import__() 等。 也许你看到这个标题,会说我怎么会发这么基础的文章? 与此相反。恰恰我觉得这篇文章的...

    Python中import机制详解

    ### Python中import机制详解 #### 一、引言 Python作为一种高级编程语言,以其优雅的语法、简洁的代码以及丰富的第三方库而闻名于世。在实际项目开发中,程序员经常需要利用`import`来引入其他模块或包的功能,...

    Python库 | import_resolve-0.1.2.tar.gz

    Python的`import`机制是程序运行的基础,它允许我们引入其他模块的功能到当前代码中。当我们在Python程序中使用`import`语句时,Python解释器会按照一定的规则查找并加载指定的模块。`import_resolve`库可能就是针对...

    python-import的规则.docx

    理解import的工作机制对于编写高效、可维护的Python程序至关重要。 首先,我们要理解模块搜索路径。当Python尝试导入一个模块时,它会按照以下顺序查找: 1. 当前目录:Python首先会在执行脚本所在的目录查找模块...

    Python插件机制实现详解

    ### Python插件机制实现详解 #### 一、插件机制概念与重要性 插件机制是一种常见的软件设计模式,它允许程序在运行时动态加载额外的功能模块或代码片段,从而扩展程序的功能。对于Python这样的解释型语言来说,...

    导致python中import错误的原因是什么

    总的来说,理解Python的模块导入机制是编写可维护和可扩展代码的关键。当你遇到`import`错误时,首先要检查模块名称、路径和依赖关系,其次考虑导入语句的语法是否正确,最后确保没有违反良好的编程实践,如避免`...

    python timestamp和datetime之间转换详解

    2. **异常处理**:在进行时间转换时,可能会遇到格式不匹配等问题,因此需要添加适当的异常处理机制,确保程序的健壮性。 3. **性能考虑**:对于大量数据的时间转换操作,需要注意算法的效率,避免因循环等操作导致...

    Python库 | lib_import-0.0.4.tar.gz

    总的来说,`lib_import`库很可能提供了对Python import机制的增强,可能包括优化导入速度、管理模块路径、处理动态导入等多种功能。对于Python开发者来说,理解和利用这样的库可以提高开发效率,简化项目结构,或者...

Global site tag (gtag.js) - Google Analytics