转自: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. Hibernate 缓存机制二(转)

    感谢:http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html 一.why(为什么要用Hibernate缓存?) Hibernate是一个 ...

  2. (转)struts2.0配置文件、常量配置详解

    一.配置: 在struts2中配置常量的方式有三种: 在struts.xml文件中配置 在web.xml文件中配置 在sturts.propreties文件中配置 1.之所以使用struts.prop ...

  3. uva 10404

    dp   1表示先手赢 #include <iostream> #include <cstdio> #include <cstring> #include < ...

  4. spoj 346

    当一个数大于等于12  那分别处以2, 3, 4之后的和一定大于本身    但是直接递归会超时    然后发现有人用map存了   膜拜..... #include <cstdio> #i ...

  5. Tiny6410 LED字符设备驱动

    1.查看用户手册 led1.led2.led3.led4 连接的分别是 GPK4.GPK5.GPK6.GPK7 2.查询6410芯片手册 下面还需要3个步骤: 1.设置GPIO为OUTPUT. 将GP ...

  6. C++中怎么获取类的成员函数的函数指针?

    用一个实际代码来说明. class A { public: staticvoid staticmember(){cout<<"static"<<endl;} ...

  7. struts2 标签库 介绍

    struts2.0里的标签没有分类,只用在jsp头文件加上<%@ taglib prefix="s" uri="/struts-tags" %>就能 ...

  8. Weblogic下部署的应用,当更新文件时需要重新安装部署

    JSP页面检查(秒):-1 Servlet重新加载检查(秒):-1 -1说明从不检查,故当更新文件时,需要重新部署,或重新安装部署.

  9. codeforces #305 B Mike and Feet

    跟之前做过的51Nod的移数博弈是一样的QAQ 我们考虑每个数的贡献 定义其左边第一个比他小的数的位置为L 定义其右边第一个比他小的数的位置为R 这个可以用排序+链表 或者 单调队列 搞定 那么对于区 ...

  10. No ongoing transaction. Did you forget to call multi?

    2016-10-21 14:41:47,551 [ERROR] [http-nio-8032-exec-2] TransactionSynchronizationUtils:171 - Transac ...