1、模块导入方法
常见的场景:
一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀,导入模块可以实现功能的重复利用
import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
a. import语句
python 内置了很多模块,比如os、sys、time等,也可以是自定义模块、模块包、C扩展等,使用import无法区分导入的模块类型
import 模块名
例如:导入spam.py
import spam(不含.py)
导入多个模块:
import os,time,sys
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块import很多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句)
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
导入模块干了哪些事:
1 执行源文件
2 以一个源文件的全局名称空间
3 在当前位置拿到一个模块名,指向2创建的名称空间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#测试一:money与spam.money不冲突
#test.py
import
spam
money
=
10
print
(spam.money)
输出:
from
the spam.py
1000
#测试二:read1与spam.read1不冲突
#test.py
import
spam
def
read1():
print
(
'========'
)
spam.read1()
输出:
from
the spam.py
spam
-
>read1
-
>money1000
#测试三:执行spam.change()操作的全局变量money仍然是spam中的
#test.py
import
spam
money
=
1
spam.change()
print
(money)
输出:
from
the spam.py
1
|
模块别名功能
练习:
有两钟sql模块mysql和oracle,根据用户的输入,选择不同的sql功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#mysql.py
def
sqlparse():
print
(
'from mysql sqlparse'
)
#oracle.py
def
sqlparse():
print
(
'from oracle sqlparse'
)
#test.py
db_type
=
input
(
'>>: '
)
if
db_type
=
=
'mysql'
:
import
mysql as db
elif
db_type
=
=
'oracle'
:
import
oracle as db
db.sqlparse()
|
为已经导入的模块起别名的方式对编写可扩展的代码很有用,假设有两个模块xmlreader.py和csvreader.py,它们都定义了函数read_data(filename):用来从文件中读取一些数据,但采用不同的输入格式。可以编写代码来选择性地挑选读取模块
1
2
3
4
5
|
if
file_format
=
=
'xml'
:
import
xmlreader asreader
elif
file_format
=
=
'csv'
:
import
csvreader asreader
data
=
reader.read_date(filename)
|
b. from…import语句
from 模块名 import 模块名中的方法
例如:from spamimport money,read1,read2,change
如果模块中的方法太多,可以使用:
from spam import * (不推荐使用,容易与执行文件的命名空间冲突)
__all__=['money','x'] #对from spam import * 有用,之后导入money、x方法
_money=1000 #对from spam import * 有用,不会导入这个方法
对比import spam,会将源文件的名称空间'spam'带到当前名称空间中,使用时必须是spam.名字的方式,而from 语句相当于import,也会创建新的名称空间,但是将spam中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#spam.py
print
(
'from the spam.py'
)
money
=
0
def
read1():
print
(
'spam->read1->money'
,money)
def
read2():
print
(
'spam->read2 calling read'
)
read1()
def
change():
global
money
money
=
0
# 执行文件
from
spam
import
money,read1,read2,change
money
=
0
print
(money)
print
(read1)
输出:
from
the spam.py
#首先执行spam.py
0
#仍然是当前执行文件的命名空间中的money
<function read1 at
0x00000000026DE950
>
|
优点:使用源文件内的名字时无需加前缀,使用方便
缺点:容易与当前文件的名称空间内的名字混淆
c. 模块搜索路径
模块只在第一次导入时才会执行,之后的导入都是直接引用内存已经存在的结果
import sys
print('spam' in sys.modules) #存放的是已经加载到内的模块
注意:自定义的模块名一定不要与python自带的模块名重名
模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
1
2
3
4
5
6
7
8
9
|
import
time
import
importlib
import
spam
#导入模块会把硬盘中的模块内容加载到内存中
time.sleep(
20
)
import
spam
#再次导入会直接从内存中查找,忽略硬盘中模块内容
print
(spam.money)
importlib.
reload
(spam)
#会重新加载模块(只在测试环境使用)
print
(spam.money)
|
import sys
print(sys.path) #模块的搜索路径
sys.path从以下位置初始化
1 执行文件所在的当前目录
2 PTYHONPATH(包含一系列目录名,与shell变量PATH语法一样)
3 依赖安装时默认指定的
加入模块路径:
1
2
3
4
|
import
sys
print
(sys.path)
sys.path.insert(
0
,r
'要添加的模块路径'
)
#插入模块路径
sys.path.append(r
'要添加的模块路径'
)
#追加模块路径
|
d. 区分python文件的两种用途
文件当做脚本(执行文件)运行时__name__等于__main__
文件当做模块被加载运行时__name__等于模块名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# m1.py
import
os,sys
x
=
1
def
func1():
print
(
'from m1'
)
def
func2():
print
(
'from m2'
)
def
func3():
print
(
'from m3'
)
# print(__name__)
#文件当做脚本运行时__name__等于__main__
#文件当做模块被加载运行时__name__等于模块名
if
__name__
=
=
'__main__'
:
#当做脚本使用时才执行
func1()
func2()
func3()
# run.py
import
m1
#导入m1模块
m1.func3()
|
e. 包
python3中创建文件夹会自动创建__init__.py
python2中创建包需要手动创建__init__.py
1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
强调:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
3.凡是在导入时带点的,点的左边都必须是一个包
本文转自lyndon博客51CTO博客,原文链接http://blog.51cto.com/lyndon/1953171如需转载请自行联系原作者
迟到的栋子