import做了什么

sys.modules

  1. 中寻找该模块是否之前被引入过,如果有,引入该名字[

import mode

  1. 相当于

mod = sys.modules['mod']

  1. ]
  2. 如果没有:

sys.path

  1. 中寻找该模块,如果没找到,报错
  2. 如果找到,创建一个空的模块对象,通常为

dict()

  1. 将该模块写入

sys.modules

  1. 加载该模块文件(如果有必要,先编译)
  2. 执行该模块代码,

def

import

class

  1. 实际上都是表达式,执行之后才可以被访问
形式
from mod import *
'''
for all public_name in mod:
    sys.modules[public_name] = public_name的定义
'''

备注:

  • 只能出现在模块作用域
  • mod本身没有被引入,因此mod.name会报错
  • 会寻找该模块定义的公共名字(public names),如果有

__all__

  • 的定义,那么该变量定义的名字均为公共的,否则该模块中不以

_

  • 开头的名字将被视为公共名字
import X
'''
sys.modules['X'] = X的定义
'''

备注:

  • 只能引入包或模块,不能引入模块内定义的类、函数或变量
  • 如果X是包,会执行init.py,如果里面有import,则会在sys.modules加入引入的模块
from mod import foo
'''
foo 可以为包、模块、类、函数、变量
submodules['mod'] = mod的定义
submodules['mod.foo'] = mod.foo的定义
'''
最佳实践
  • 不要使用

from module import *

  • 在文件的开始处

import

  • 所需的模块
  • 以下列顺序

import

  • 不同的模块:
  1. 系统库的模块,如

os

sys

  1. 等;
  2. 第三方的模块
  3. 当前工程自定义的模块
  • 不使用相对路径的

import

  • ,永远使用绝对路径

import

  •  参考PEP328
  • 可以在函数内

import

  • ,比如平台相关的代码,或者降低模块初始化的耗时
  • 如果某个类的对象需要使用某个模块,可以在

__init__(self)

import

  • 该模块并且赋值为该类对象的一个成员变量,这样该模块在对象整个生命周期都是可用的,但一定要写在函数内,如果没有,那么实际上该模块的初始化是发生在该类所属模块的初始化阶段;
PEP328
  • 永远使用绝对路径

import

  • ,让所有的模块都从

sys.path

  • 中寻找,避免出现语义混淆:

import item

  • :不清楚是相对于当前模块的其他模块,还是某个package
  • 如果从一个模块或包中引入很多名字,那么使用

()

  • 括起来:
from package import (m1, m2, m3
m4, m5, m6)
  • 如果使用相对引用,那么只能使用

from <> import mod

  • ,如果使用

import mod

  • ,那么被认为是绝对引用
例子
# 文件结构:
package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py
    main.py
访问包的模块
# main.py
'''
如果package目录下的__init__.py中没有import moduleA,
下面这个语句会报错: 'module' object has no attribute 'moduleA'
原因是默认不会import一个包所包含的模块
'''
import package
print package.moduleA.foo

'''
推荐写法如下
'''
import package.moduleA as modA
print modA.foo

# 或
from package import moduleA
print moduleA.foo
相对路径引用

同一package的module相互引用

# moduleX.py
from . import moduleY
from .moduleY import spam as ham
from ..subpackage1 import moduleY

引用不同package的module

# moduleX.py
from ..subpackage2 import moduleZ
from ..moduleA import foo
from ...package import bar