转自:http://bingotree.cn/?p=569

参考《Python学习手册》,强烈建议看下这本书的相关章节。

在一些规模较大的项目中,经常可以看到通过imp、__import__导入module的例子。通过这些方法,代码可以灵活的根据需要(如配置文件)导入具体的模块。这篇文章小秦会总结一下python导入的基本知识和几种用法。

1.import的过程
比如下面这个例子:

1
import abc

这行代码会的导入abc,导入的过程是:在sys.path这个list中的路径中,按照顺序搜索名字符合要求的文件。这些文件可以
是.py、.pyc或其他如zip这类文件。如果搜索到的文件是非字节码的文件,那么python会的先把它编译成字节码然后导入。如果同时存在字节码和
非字节码的文件,则会的比较两者的修改时间戳来决定是否要重新编译生成字节码文件(所以一般的发行版可执行文件都是字节码格式的,这样可以加快导入的速
度)。找到确定的字节码文件后,python解析器会的加载该文件,文件中的所有语句会的从顶至下执行一遍,这时这个文件中所有对全局变量的赋值都会得到
对应的引用对象(def、class这类语句其实也是赋值)。这些变量都属于该导入模块的名字空间中。最后这个模块文件整体被赋值到import语句指明
的那个变量中,在这里就是我们的abc。此时abc就引用了我们的abc模块。

关于文件的搜索路径有一点要说明的是,所有的python解析器会的自动import
site模块,这个模块会的生成我们的sys.path变量,这其中包含了对.pth文件的解析。.pth里边可以包含指向某个搜索路径的文本,解析器解
析了.pth文件后会自动去其写明的路径继续搜索模块。默认情况下,sys.path的构成顺序是:程序的主目录,PYTHONPATH环境变量指定的目
录,标准链接库目录和.pth文件中写明的目录。

上面也说了,搜索文件的时候目标文件可以是.py、.pyc或其他如zip这类文件。如果说同时有abc.py,abc.zip存在,那么会的按照一定的顺序(比如.py优先于.zip)加载第一个符合要求的文件。

2.import时候的from
比如下面这个例子:

1
2
3
from a import b
#or
import a.b as b

这两行代码都从a中导入b,并赋值给b变量。看上去作用一样,实际上有一定的区别,区别在于:
a.import a.b as b中的a、b必须是一个package或module,而from则不用。换句话说,from可以直接获取属性(可以认为上面的语句的意思是先生成a对象,然后将a的b属性赋值给本地名字空间的b变量)。
b.from会的将b绑定到一个独立的对象上,这个对象在reload的时候不会的收到影响,而import则在reload的时候会的将b指向新的对象上。

3.__import__
import会的调用__import__执行实际的导入工作。一般只有在运行代码期间才知道被导入模块名字的时候才会使用这个内置方法。具体的语法可以
看:https://docs.python.org/2/library
/functions.html?highlight=__import__#__import__

这个方法在很多的项目里都有看到过,比如动态的导入基于抽象类(使用abc的meta元类)的某个实现的backend的时候会用到。

4.imp
imp模块可以实现import的所有功能,并且方便使用。比如saltstack在导入各种module的时候,就是通过imp来导入的。官方文档是https://docs.python.org/2/library/imp.html,可以在里边找到该模块的方法。

两个重要的方法是find_module和load_module,前者用于找到需要被导入module的具体名字,后者执行真正的导入操作。另外该模块还有如new_module这类方法。

这是官方文档中的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import imp
import sys
 
def __import__(name, globals=None, locals=None, fromlist=None):
    # Fast path: see if the module has already been imported.
    try:
        return sys.modules[name]
    except KeyError:
        pass
 
    # If any of the following calls raises an exception,
    # there's a problem we can't handle -- let the caller handle it.
 
    fp, pathname, description = imp.find_module(name)
 
    try:
        return imp.load_module(name, fp, pathname, description)
    finally:
        # Since we may exit via an exception, close fp explicitly.
        if fp:
            fp.close()

5.sys.modules
所有被导入的模块都会的插入到sys.modules这个字典中,字典的key是模块名,字典的value则是具体的模块对象,比如:

1
2
3
4
5
6
7
8
9
10
>>> import a
>>> import sys
>>> print sys.modules['a']
<module 'a' from 'a/__init__.pyc'>
>>> print a
<module 'a' from 'a/__init__.pyc'>
>>> id(a)
4465092264
>>> id(sys.modules['a'])
4465092264

正是由于这个字典的存在,在多个文件中import同一个模块是不会重复导入的,因此导入的时候会的先查看sys.modules中是否存在对应的
模块,只有不存在的时候才会的被导入。这个特性在某些时候不需要(比如evenelet中的绿化),因此可以先将这个字典中的某个项del掉,然后导入新
的模块。

6.绝对导入和相对导入
大部分的导入用的都是绝对导入,小秦很少见到用相对导入的代码。

绝对导入就是按照sys.path进行文件搜索的导入,而相对导入则是from中通过’.’在包中搜索对应文件的导入。通过增加’.’能保证导入只是在包中进行搜索,不会在sys.path中进行搜索。另外相对导入的搜索路径是包含导入语句的文件所在的那个目录。

比如这个例子:

1
2
3
4
5
6
7
8
9
[/tmp/a]$ls
__init__.py b
[/tmp/a]$ls b/
__init__.py x.py        y.py
[/tmp/a]$cat b/x.py
from __future__ import absolute_import
from . import y
[/tmp/a]$cat b/y.py
print('y is imported')

在a目录中,执行下面的代码可以看到y被导入了:

1
2
>>> import b.x
y is imported

如果我们将x.py的内容换成:

1
2
3
[/tmp/a]$cat b/x.py
from __future__ import absolute_import
import y

那么我们在执行导入的时候就会看到异常:

1
2
3
4
5
6
>>> import b.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "b/x.py", line 2, in <module>
    import y
ImportError: No module named y

除了’.’外,相对导入的’..’表示从文件的上层导入,’.a’表示从文件的所在路径的a模块导入。’..a’表示从上层的a模块导入。借用《Python学习手册》中的例子:
对于A.B.C这个模块中的下面的这些代码,具体的导入文件是:

1
2
3
4
5
from . import D    #导入的是A.B.D
from .. import E   #导入的是A.E
 
from .D import X   #导入的是A.B.D.X
from ..E import #导入的是A.E.X

Python中的导入的更多相关文章

  1. [python]关于在python中模块导入问题追加总结

    [背景] 最近在写程序时,我使用的eclipse编辑器运行都没有问题,然后部署到自动化环境上却偏偏报找不到相应模块问题,现在对该问题在之前的贴子上追加总结 原帖子:[python]关于python中模 ...

  2. python中模块导入问题(已解决)

    想在python中导入request包: 无此模块,于是先安装requests包: 但是提示"Requirement already satisfied".在提示的相应目录里,找到 ...

  3. 关于python中文件导入的若干问题

    __init__文件 同一级目录下直接import导入就可以了,如果是在不同的目录下面被导入文件的文件夹下面必须有__init__.py文件,即使这个文件是空的也可以.当然这个文件也可以初始一些数据 ...

  4. python 中如何导入一个自己创建的模块

    导入模块的语句的三种方法: 1.import module 2.from module import name1,[name2,name3....] 3.from module import * 先看 ...

  5. 解决Python中PyCharm导入模块时,模块名下出现红色波浪线的问题

    在博主第一次在PyCharm中导入模块时,模块名下出现红色波浪线,不影响程序执行,但强迫症忍不了 以下是解决办法 Let's do it ... 进入设置,找到Console下的Python Cons ...

  6. 在python中重新导入模块

    重新加载模块 倘若,更改了已经在 Python shell 中导入的模块,然后重新导入该模块,Python 会认为“我已经导入了该模块,不需要再次读取该文件”,所以更改将无效. 要解决这个问题,有以下 ...

  7. Python中import导入上一级目录模块及循环import问题的解决

    转自:https://www.cnblogs.com/sjy18039225956/p/9265461.html 使用python进行程序编写时,经常会使用第三方模块包.这种包我们可以通过python ...

  8. 【python】关于python中模块导入的总结

    precondition:比如我有如下这样的文件目录结构 说明:add和debug两个包都隶属于src目录,它们是同级目录,其中在add路径下有一个add.py的模块,里面定义了一个jiafa()的函 ...

  9. python中动态导入模块

    当导入的模块不存在时,就会报ImportError错误,为了避免这种错误可以备选其他的模块或者希望优先使用某个模块或包,可以使用try...except...导入模块或包的方式. 例如: Python ...

随机推荐

  1. Web网站架构设计

    目录 [隐藏/显示] 1 - Web负载均衡   1.1 - 使用商业硬件实现   1.2 - 使用开源软件   1.3 - 使用windows自带的互载均衡软件   1.4 - 总结2 - 静态网站 ...

  2. 【数位DP】Hdu 2089:不要62

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  3. PAT-乙级-1015. 德才论 (25)

    1015. 德才论 (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Li 宋代史学家司马光在<资治通鉴&g ...

  4. WP-Syntax 插件使用方法

    技术博客中使用WP-Syntax将代码高亮是最常见的.而一段时间不用总会忘记每种语言的的pre标签的值. 这里简单介绍下,WP-Syntax 是一个针对 Wordpress 的代码高亮插件,最大的优点 ...

  5. css3属性整理

    浏览器内核:主流内容主要有Mozilla(熟悉的有Firefox,Flock等浏览器).WebKit(熟悉的有Safari.Chrome等浏览器).Opera(Opera浏览器).Trident(讨厌 ...

  6. 关于用 MySQL 存储 Emoji

    http://www.v2ex.com/t/137724 如果你希望让你的网站或者 App 支持 Emoji,那么在初次设置 MySQL 时,有一些细节你需要知道. Emoji Emoji 字符的特殊 ...

  7. hibernate annotation注解 columnDefinition用法

    column注解中的columnDefinition属性用于覆盖数据库DDL中的语句:(MySql) @Column(columnDefinition = "int(11) DEFAULT ...

  8. ExtJS4 MVC开发教程:搭建开发环境

    原文地址:http://www.lihuai.net/qianduan/extjs/864.html 博主系列教程:http://www.lihuai.net/qianduan/extjs 在所有的J ...

  9. [矩阵快速幂]HDOJ4565 So Easy!

    题意:给a, b, n, m 求 $\left \lceil ( a+ \sqrt b )^n \right \rceil$ % m 看到 $( a+ \sqrt b )^n$ 虽然很好联想到共轭 但 ...

  10. Android:ViewPager适配器PagerAdapter的使用

    PageAdapter是一个抽象类,直接继承于Object,导入包android.support.v4.view.PagerAdapter即可使用. 要使用PagerAdapter, 首先要继承Pag ...