一、背景
最近在学pyhon的web框架Karrigell,下载了源码之后运行,出现了error:
ImportError:No module named k_target
在www/index.py里面importk_target,但是运行的时候出现了上述错误,网上查了一下,知道
是不同目录下 import模块或者包的话,需要将模块或者包的路径加入到sys.path中。于是使用了
sys.path.append('e:\Karrigell\karrigell\core')解决了问题。借此机会又重新学习了一下python的
import机制和搜索路径。
二、python的import机制
2.1 模块和包
模块化编程使得软件开发更加灵活,不同的功能可多人协作完成,同时便于代码复用和后期维护,
python使用import模块/包来组织各个模块,使不同模块直接可以调用。
模块:python中,每个py文件被称之为模块,它可以定义变量,方法和类;
包:是一个目录,它可以包含py文件和子目录,最重要的一点是包一定含有一个__init__.py文件。
只要模块或者包所在的目录在sys.path中,就能使用import 来引用其他模块内的变量,方法和类。
2.2 import的过程
1. Python中所有加载到内存的模块都放在sys.modules。当import一个模块时首先会在这个列表中
查找是否已经加载了此模块,如果加载了则只是将模块的名字加入到正在调用import的模块的
Local名字空间中。如果没有加载则从sys.path目录中按照模块名称查找模块文件,模块文件可以
是py、pyc、pyd,找到后将模块载入内存,并加入到sys.modules中,并将名称导入到当前的
Local名字空间。若没有找到,则import没有效果,运行时出现ImportError:Nomodule named ***.
所以: import A
|
查看sys.moudles--->找到,导入模块名字到当前模块
|
没有找到,则搜索sys.path--->找到,模块加载到内存,加入sys.moudles
|
没有找到,则import没有效果
2.每个模块在内存只有一份,即pyModuleObject对象只有一个,首次import该模块时加载到内存,
然后存放在sys.modules里,其他模块再引用该模块的时候,在sys.modules里面可以直接找到。
2.3 包的import
前面已经讲了只要有__init__.py,这个目录都可以称为一个包。包下面的子目录也可以是子包。
如果查看包的类型importSQLAlchemy type(SQLAlchemy),可以看到其实也是<type'module'>。
所以import包的时候,查找路径也是sys.path,加载到内存后也会放在sys.modules中。
import包的时候,需要考虑__init__.py,因为首次导入包的时候会执行此文件里面的语句而不是
模块里面的语句,例如执行importpackage;就会执行__init__.py文件,如果想在导入包时做一些
初始化工作,eg:导入其他的包都可以写在这个文件里面。eg:列表__all__=["module1","module2"],
它包含了执行 from package import *时导入的模块。
2.4 import的使用
如果想要引用某个模块A.py中内容,有两种方法:
1.import A; A.func()这实际上是把整个A的代码在当前环境中执行了一遍,A模块里面的变量,
方法都可以被当前模块引用
2.from A import func;func();这个是在当前环境中建立和变量func()同名的对象,并且将A中的
变量赋值给它,直接引用变量或者方法,但是你不能在当前模块里面定义同名的变量或者函数。
注意:import只能模块,包,而不能直接import变量,函数,类。importA.func()就是错的。
如果想要引用某个包B,也有几种方法:
1.import B; 想要使用B包下面A模块的func,B.A.func()-----这时,一定要在__init__里进行一些
初始化设定,否则内存中只加载了B,并没有加载模块A,func()调用不到
2.import B.A ; B.A.func()
3.from B import A; A.func() from B import *,可以引用所有的模块
4.from B.A import func; func()
5.from B import A as a1;为A取了别名
2.5 import的嵌套
1. A模块importB, B模块importC,A中建立了一个local的名字空间B,A模块只能访问B中的变量
和函数,而不能访问C的。如果想访问C,只能importC。
2. A模块importB,B模块importA.参考:http://blog.csdn.net/sinat_16790541/article/details/43376741
三、模块的搜索路径
由前面我们知道import模块的时候,如果模块没有在sys.modules里面,即没有加载进内存,
那么会去sys.path里面搜索模块,这里sys.path就是模块的搜索路径,如果看一个模块能不能
import成功,就看它是否在sys.path里面可以找到。
1. sys.path的第一个选项,是主模块所以目录,在交互环境下是一个空项,对应当前目录。
2.在windows下,若设置了PYTHONPATH,那么这里设定的路径会被自动添加到sys.path里面,
所以可以自己添加PYTHONPATH
3.将自己想要import的模块或者包的路径添加到sys.path里,sys.path.append("路径名”)
-------但是这是暂时性的,只要重新运行python,这个路径就消失了
4.将自己想要import的模块或者包放到site_packages目录下.
(from distutils.sysconfig import get_python_lib; printget_python_lib()显示site-packages目录)
5.使用pth文件,在site-packages文件中创建.pth文件,将模块的路径写进去,一行一个路径
6.将自己想要import的模块添加到$python_dir/lib