Python中的导入
转自: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 X #导入的是A.E.X |
Python中的导入的更多相关文章
- [python]关于在python中模块导入问题追加总结
[背景] 最近在写程序时,我使用的eclipse编辑器运行都没有问题,然后部署到自动化环境上却偏偏报找不到相应模块问题,现在对该问题在之前的贴子上追加总结 原帖子:[python]关于python中模 ...
- python中模块导入问题(已解决)
想在python中导入request包: 无此模块,于是先安装requests包: 但是提示"Requirement already satisfied".在提示的相应目录里,找到 ...
- 关于python中文件导入的若干问题
__init__文件 同一级目录下直接import导入就可以了,如果是在不同的目录下面被导入文件的文件夹下面必须有__init__.py文件,即使这个文件是空的也可以.当然这个文件也可以初始一些数据 ...
- python 中如何导入一个自己创建的模块
导入模块的语句的三种方法: 1.import module 2.from module import name1,[name2,name3....] 3.from module import * 先看 ...
- 解决Python中PyCharm导入模块时,模块名下出现红色波浪线的问题
在博主第一次在PyCharm中导入模块时,模块名下出现红色波浪线,不影响程序执行,但强迫症忍不了 以下是解决办法 Let's do it ... 进入设置,找到Console下的Python Cons ...
- 在python中重新导入模块
重新加载模块 倘若,更改了已经在 Python shell 中导入的模块,然后重新导入该模块,Python 会认为“我已经导入了该模块,不需要再次读取该文件”,所以更改将无效. 要解决这个问题,有以下 ...
- Python中import导入上一级目录模块及循环import问题的解决
转自:https://www.cnblogs.com/sjy18039225956/p/9265461.html 使用python进行程序编写时,经常会使用第三方模块包.这种包我们可以通过python ...
- 【python】关于python中模块导入的总结
precondition:比如我有如下这样的文件目录结构 说明:add和debug两个包都隶属于src目录,它们是同级目录,其中在add路径下有一个add.py的模块,里面定义了一个jiafa()的函 ...
- python中动态导入模块
当导入的模块不存在时,就会报ImportError错误,为了避免这种错误可以备选其他的模块或者希望优先使用某个模块或包,可以使用try...except...导入模块或包的方式. 例如: Python ...
随机推荐
- 第一章 Spring整体框架和环境搭建
1.Spring 的整体架构 Spring框架主要由7大模块组成,它们提供了企业级开发需要的所有功能,而且每个模块都可以单独使用,也可以和其他模块组合使用,灵活且方便的部署可以使开发的程序更加简洁灵活 ...
- SQL 聚集函数使用
SQL 聚集函数使用 (2009-04-14 15:50:36) 转载▼ 总结: 在SQL语句中同时包含where子句,groupby子句,having子句及聚集函数时的执行顺序: 1.按WHER ...
- shuffle过程中的信息传递
依据Spark1.4版 Spark中的shuffle大概是这么个过程:map端把map输出写成本地文件,reduce端去读取这些文件,然后执行reduce操作. 那么,问题来了: reducer是怎么 ...
- 安卓 DevOps:从一次推送命令到生产
DevOps 是一种广为人知的活动,其主要目的是使软件交付自动化.的确,DevOps 的目标是持续测试.代码质量.功能开发和更轻松地进行维护更新.因此,DevOps 的终极目标之一是让开发者可以执行快 ...
- secureCRT中文字符乱码
1.远程linux机器.修改环境变量LANG.例如在~/.bash_profile里面添加 export LANG=zh_CN.UTF8 2.本地windows机器.修改SecureCRT的设置.找到 ...
- 嵌入式开发之NorFlash 和NandFlash
http://blog.csdn.net/tigerjibo/article/details/9322035 [摘要]:作为一个嵌入式工程师,要对NorFlash 和NandFlash要有最起码的认知 ...
- Java泛型:泛型类、泛型接口和泛型方法
根据<Java编程思想 (第4版)>中的描述,泛型出现的动机在于: 有许多原因促成了泛型的出现,而最引人注意的一个原因,就是为了创建容器类. 泛型类 容器类应该算得上最具重用性的类库之一. ...
- 手机金属外壳加工工艺:铸造、锻造、冲压、CNC
现如今金属手机成为行业的热点,在消费电子产品中应用越来越广,本文详细介绍几种金属加工工艺及相关产品应用. 1.CNC+阳极:iPhone 5/6, HTC M7 2.锻造+CNC:华为P8,HTC M ...
- Cinema 4D R16安装教程
CINEMA 4D_百度百科 http://baike.baidu.com/view/49453.htm?fr=aladdin 转自百度贴吧 [教程]Cinema 4D R16新功能介绍及安装教程_c ...
- profile工具
gprof callgrind vtune(待使用) ----time命令(待学习) ps -u <username> -H -opid,cmd strace