【python学习手册】第23章模块包

写在前面,一些习题解答和自己想法

习题解答

  1. 模块包目录内的__init__.py文件有何用途

    用于声明和初始化,当导入模块包时,会执行该文件内的代码
    
  2. 每次引用包的内容时,如何避免重复包的完整路径

    使用from 语句可以缩短包的路径
    
    例如包dir1.dir2.dir3.foo
    
    from dirr1.dir2.dir3 import foo
    
    引用的时候,可以只用foo的名称
    
  3. 哪些目录需要init.py文件?

    包模块中每个目录都需要该文件,哪怕是空文件。
    
  4. 在什么情况下必须通过import而不能通过from使用包

    当你需要导入的包或者变量,和某个变量名称重复时,使用import 语句可以避免命名冲突
    
  5. from mypkg import spam 和from . import spam有什么差别

    前者是绝对导入,后者是相对导入
    

总结一下模块导入:

  1. 模块导入有两种语法形式,一种是import xx.xx.xx
    另外一种是 from dir1.dir2 import test test可以是模块,也可以是变量

  2. 模块的搜索顺序:

    1.程序的主目录 或者叫做CWD
    2.PYTHONPATH 环境变量
    3.标准库
    4.前三者目录下的.pth文件
    
  3. 相对导入和绝对导入

    一般的在包的外部,对某个包进行导入时,既可以使用from 也可以使用import,不可以用 点(.) ,按照上面的搜索规则进行搜索。

    下面仅仅是包的内部进行导入时会发生的一些规则变化,自己编写包的时候需要注意到:

    在包的内部进行导入时,增加了相对导入,使得可以显式的仅导入包内相对目录的某个包,例如from . import apple

    而没有 点(.)的时候,py2.6就会先搜索相对路径,再搜索绝对路径 (也是先CWD再其他目录)。

    这样就存在一个问题,如果不想搜索相对路径,直接搜索绝对路径或者标准库,就做不到的。

    如果是要在包内导入某个标准库string,包内的相对路径也是string

    这个让我想到一个例子,有助于理解

    import apple 就是我要吃苹果,一般都是先吃手里的,再去商店买
    
    from . import apple  就是只吃自己手里的苹果
    
    如果想直接去商店买,是不行的。
    

    python3就做出了修改:

    包的内部进行导入时,忽略包内
    import apple 会直接找商店买
    

    python2 如果也想这样,加入下面这一句就可以:

    from __future__ import absolute_import
    

code1

在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所在目录找模块

code2

删一下当前目录下的所有文件 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。
就是直接去商店,不吃自己家的。

append code3

加入一个文件

包内导入:

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开始找,就是程序主目录(见模块的搜索顺序)。
posted @ 2016-03-22 17:40  程序员杰诺斯  阅读(113)  评论(0编辑  收藏  举报