写在前面,一些习题解答和自己想法
模块包目录内的__init__.py文件有何用途
用于声明和初始化,当导入模块包时,会执行该文件内的代码
每次引用包的内容时,如何避免重复包的完整路径
使用from 语句可以缩短包的路径
例如包dir1.dir2.dir3.foo
from dirr1.dir2.dir3 import foo
引用的时候,可以只用foo的名称
哪些目录需要init.py文件?
包模块中每个目录都需要该文件,哪怕是空文件。
在什么情况下必须通过import而不能通过from使用包
当你需要导入的包或者变量,和某个变量名称重复时,使用import 语句可以避免命名冲突
from mypkg import spam 和from . import spam有什么差别
前者是绝对导入,后者是相对导入
总结一下模块导入:
模块导入有两种语法形式,一种是import xx.xx.xx
另外一种是 from dir1.dir2 import test test可以是模块,也可以是变量
模块的搜索顺序:
1.程序的主目录 或者叫做CWD
2.PYTHONPATH 环境变量
3.标准库
4.前三者目录下的.pth文件
相对导入和绝对导入
一般的在包的外部,对某个包进行导入时,既可以使用from 也可以使用import,不可以用 点(.) ,按照上面的搜索规则进行搜索。
下面仅仅是包的内部进行导入时会发生的一些规则变化,自己编写包的时候需要注意到:
在包的内部进行导入时,增加了相对导入,使得可以显式的仅导入包内相对目录的某个包,例如from . import apple
而没有 点(.)的时候,py2.6就会先搜索相对路径,再搜索绝对路径 (也是先CWD再其他目录)。
这样就存在一个问题,如果不想搜索相对路径,直接搜索绝对路径或者标准库,就做不到的。
如果是要在包内导入某个标准库string,包内的相对路径也是string
这个让我想到一个例子,有助于理解:
import apple 就是我要吃苹果,一般都是先吃手里的,再去商店买
from . import apple 就是只吃自己手里的苹果
如果想直接去商店买,是不行的。
python3就做出了修改:
包的内部进行导入时,忽略包内
import apple 会直接找商店买
python2 如果也想这样,加入下面这一句就可以:
from __future__ import absolute_import
在2.7.10和3.5.1同时测试
包外导入(没有区别):
test\string.py
print("string " * 4)
test\run.py
import string
print(string)
run
python run.py
string string string string
<module 'string' from '/root/py30/test/string.py'>
执行过程,先从主目录也就是run.py所在目录找模块
删一下当前目录下的所有文件 rm -rf string.py
包内导入:
test\pkg\__init__.py
#This is pkg module
test\pkg\string.py
print("string " * 4)
test\pkg\egg.py
import string
print(string)
test\run.py
import pkg.egg
print("run")
python2.7:
python run.py
string string string string
<module 'pkg.string' from '/root/py30/test/pkg/string.py'>
python3.5:
python run.py
<module 'string' from '/root/.pyenv/versions/3.5.1/lib/python3.5/string.py'>
注意到,python3 在包内执行语句import string
的时候,直接忽略了包内的string.py。
就是直接去商店,不吃自己家的。
加入一个文件
包内导入:
test\pkg\__init__.py
#This is pkg module
test\pkg\string.py
print("string " * 4)
test\pkg\egg.py
import string
print(string)
test\string.py
print(“this is cwd string module”)
test\run.py
import pkg.egg
print("run")
python2.7:
python run.py
string string string string
<module 'pkg.string' from '/root/py30/test/pkg/string.py'>
python3.5:
python run.py
this is cwd string module
<module 'string' from '/root/py30/test/string.py'>
注意到,python3 虽然忽略了包内的string.py,然后从cwd开始找,就是程序主目录(见模块的搜索顺序)。