Python 模块与包

模块:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

但其实import加载的模块分为四个通用类别: 

1、使用python编写的代码(.py文件)

2、已被编译为共享库或DLL的C或C++扩展

3、包好一组模块的包

4、使用C编写并链接到python解释器的内置模块

一、import语句

import语句作用就是用来导入模块的,它可以出现在程序中的任何位置。

用法:

使用import语句导入模块,import语句语法如下:

import module关键字 模块名

使用方法例如:

import math       #入导math模块
math.floor()        #调用math模块中的floor()函数

如果要同时导入多个模块,只需要在模块名之前用逗号进行分隔:

import module1,module2,module3.......

同时导入多个模块的方法,对于初学者来说可读性和可理解性不如第一种好。所以想要导入多个模块时,还是比较推荐用第一种方式,把每一个模块都单独进行一次导入,可能会感觉操作起来麻烦一些,但便于理解。

为模块名起别名,相当于m1=1;m2=m1

import spam as sm
print(sm.money)

二、form…impot语句

form…impot语句也是导入模块的一种方法,更确切的说是导入指定的模块内的指定函数方法。

from-import语句语法

from module import name 关键字 模块名 关键字 方法名

例如入导函数math模块中的floor函数方法:

from math import floor

form…impot使用方法例如:

from math import floor     #导入math模块中的floor函数方法
floor()                    #调用floor()函数方法

三、模块搜索路径

python解释器在启动时会自动加载一些模块,可以使用sys.modules查看在第一次导入某个模块时(比如spam),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用,如果没有,解释器则会查找同名的内建模块,如果还没有找到就从sys.path给出的目录列表中依次寻找spam.py文件。所以总结模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块

sys.path的初始化的值来自于:

The directory containing the input script (or the current directory when no file is specified).

PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).

The installation-dependent default.

需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错。

在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载。

import sys
print(sys.modules)
 #查询结果

{'builtins': <module 'builtins' (built-in)>, 'sys': <module 'sys' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>,
'_warnings': <module '_warnings' (built-in)>, '_thread': <module '_thread' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_frozen_importlib_external':
<module '_frozen_importlib_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>,
'winreg': <module 'winreg' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, 'encodings': <module 'encodings' from 'C:\\Python36\\lib\\encodings\\__init__.py'>,
'codecs': <module 'codecs' from 'C:\\Python36\\lib\\codecs.py'>, '_codecs': <module '_codecs' (built-in)>, 'encodings.aliases': <module 'encodings.aliases' from 'C:\\Python36\\lib\\encodings\\aliases.py'>,
'encodings.utf_8': <module 'encodings.utf_8' from 'C:\\Python36\\lib\\encodings\\utf_8.py'>, '_signal': <module '_signal' (built-in)>, '__main__':
<module '__main__' from 'F:/python/作业/4day/2.py'>, 'encodings.latin_1': <module 'encodings.latin_1' from 'C:\\Python36\\lib\\encodings\\latin_1.py'>, 'io':
<module 'io' from 'C:\\Python36\\lib\\io.py'>, 'abc': <module 'abc' from 'C:\\Python36\\lib\\abc.py'>, '_weakrefset': <module '_weakrefset' from 'C:\\Python36\\lib\\_weakrefset.py'>,
'site': <module 'site' from 'C:\\Python36\\lib\\site.py'>, 'os': <module 'os' from 'C:\\Python36\\lib\\os.py'>, 'errno': <module 'errno' (built-in)>, 'stat': <module 'stat' from 'C:\\Python36\\lib\\stat.py'>,
'_stat': <module '_stat' (built-in)>, 'ntpath': <module 'ntpath' from 'C:\\Python36\\lib\\ntpath.py'>, 'genericpath': <module 'genericpath' from 'C:\\Python36\\lib\\genericpath.py'>, 'os.path':
<module 'ntpath' from 'C:\\Python36\\lib\\ntpath.py'>, '_collections_abc': <module '_collections_abc' from 'C:\\Python36\\lib\\_collections_abc.py'>, '_sitebuiltins': <module '_sitebuiltins' from
'C:\\Python36\\lib\\_sitebuiltins.py'>, 'sysconfig': <module 'sysconfig' from 'C:\\Python36\\lib\\sysconfig.py'>}

#排在前的目录,优先被搜索

四、包的导入

包是一种通过使用‘.模块名’来组织python模块名称空间的方式。

1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法

2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)

3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件

强调:

1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错

2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块

glance/                   #Top-level package

├── __init__.py      #Initialize the glance package

├── api                  #Subpackage for api

│   ├── __init__.py

│   ├── policy.py

│   └── versions.py

├── cmd                #Subpackage for cmd

│   ├── __init__.py

│   └── manage.py

└── db                  #Subpackage for db

    ├── __init__.py

    └── models.py

 

#文件内容

#policy.py

def get():

    print('from policy.py')

#versions.py

def create_resource(conf):

    print('from version.py: ',conf)

#manage.py

def main():

    print('from manage.py')

#models.py

def register_models(engine):

    print('from models.py: ',engine)

在glance下__init__.py添加:

from glance.api.policy import get
from glance.api.versions import create_resource
from glance.cmd.manage import main
from glance.db.models import register_models

注意事项

1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。

2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

3.对比import item 和from item import name的应用场景:

如果我们想直接使用name那必须使用后者。

五、绝对导入与相对导入

我们的最顶级包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:

绝对导入:以glance作为起始

相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)

例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py

在glance/api/version.py

#绝对导入

from glance.cmd import manage
manage.main()

#相对导入

from ..cmd import manage
manage.main()

测试结果:注意一定要在于glance同级的文件中测试

from glance.api import versions 

修改上面 用相对导入:

from .api.policy import get
from .api.versions import create_resource
from .cmd.manage import main
from .db.models import register_models
posted on 2017-08-04 11:18  wangyinhu1208  阅读(321)  评论(0编辑  收藏  举报