转载至:https://cloud.tencent.com/developer/article/1175296
模块:
在Python中,一个.py文件就称之为一个模块(Module)。
它是实现了某个功能的代码集合。
模块分为三种:
1.自定义模块
2.内置标准模块(又称标准库)
3.开源模块
模块导入方法:
1. import module_name (导入一个模块)
2. import module_name,module2_name (导入多个模块)
3. from module_name import * (不推荐使用)
4. from module_name import m1 as name_m1 (导入指定的函数或变量并重命名)
5. from module_name import m1,m2,m3 (导入模块的多个函数或变量)
第3种办法,不推荐使用。因为这一段话,相当于把module_name.py的所有代码复制到当前代码中,调用的时候,直接写方法名调用,不需要module_name.方法名()这种方式调用。如果发现方法名或者变量冲突,以本代码为准。
import的本质
把导入模块的所有代码解释一遍,统一赋值给一个变量,这个变量名叫模块名。
调用变量,使用 module_name.变量名
调用函数,使用 module_name.函数名()
from的本质
把导入模块的指定函数或者变量,放到当前文件的位置,执行一遍。
调用变量或者函数的时候,直接使用即可,不需要在前面加模块名。
自定义一个模块
新建文件hello.py,新建文件test.py,导入模块。注意,模块名是去除.py之后的名字
name = "zhang"
def say_hello():
print("hello,",name)
import hello
#输出变量,执行方法
print(hello.name)
hello.say_hello()
执行输出
zhang
hello, zhang
包:
用来从逻辑上组织模块,本质就是一个目录(必须带有一个init.py文件)
导入包的本质:
去执行包目录下的init.py文件
使用pycharm编辑器,新建一个包package_test
编辑init.py文件
print('from the package package_test')
新建一个文件p_test.py
import package_test
目录结构如下:
.
├── p_test.py
└── package_test
└── init.py
执行p_test.py,输出
from the package package_test
上面介绍的模块导入,都是基于同级目录的。那么module在不同目录下,该如何导入呢?
目录结构如下:
.
├── hello.py
└── package_test
├── init.py
└── main.py
main.py需要导入hello模块
先来分析一个导入模块的执行步骤
import module_name->找到module_name.py文件->找到module_name.py的路径->sys.path(搜索路径)
编辑main.py,打印sys.path
import sys
print(sys.path)
使用cmd执行,执行输出
['E:\python_script\day5\package_test', 'C:\Program Files\Python36\python36.zip', 'C:\Program Files\Python36\DLLs', 'C:\Program Files\Python36\lib', 'C:\
\Program Files\Python36', 'C:\Program Files\Python36\lib\site-packages']
第一个元素,就是当前路径
如果一个元素找不到,就会找下一个元素,直到所有的目录都还找不到的话,就报错
ModuleNotFoundError: No module named 'xxx'
为了解决这个问题,需要加一个路径,必须要包含需要导入模块的路径。这个路径,一般为项目根目录。
编辑main.py,先来打印当前文件的绝对路径
import sys,os
print(os.path.abspath(file))
执行输出
E:\python_script\day5\package_test\main.py
然后获取当前目录
import sys,os
print(os.path.dirname(os.path.abspath(file)))
执行输出
E:\python_script\day5\package_test
最后获取上一层目录,定义变量
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
print(BASE_DIR)
执行输出
E:\python_script\day5
这个目录,就可以找到package_test路径了!
将项目根目录添加到系统环境变量中
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
sys.path.append(BASE_DIR)
最后导入模块,执行函数
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
sys.path.append(BASE_DIR)
import hello
hello.say_hello()
执行输出
hello, zhang
注意:
sys.path.append(BASE_DIR) 是将项目根目录追加到最后一个列表元素。如果中间某一个元素,正好找到了指定文件,比如hello.py,那么就不会再查找后面的路径了,直接加载。
如果出现了这种情况,必须要把BASE_DIR插入到第一个元素位置,使用insert方法
sys.path.insert(0,BASE_DIR)
print(sys.path)
执行输出
['E:\python_script\day5', 'E:\python_script\day5\package_test', 'E:\python_script', 'C:\Program Files\Python36\python36.zip', 'C:\Program Files\Python36\DLLs', 'C:\Program Files\Python36\lib', 'C:\Program Files\Python36', 'C:\Program Files\Python36\lib\site-packages']
举另外一个例子
main.py需要调用test1.py里面的函数,目录结果如下:
.
├── module_test
│ └── main.py
└── package_test
├── init.py
└── test1.py
test1.py内容如下:
def test():
print('in the test1')
main.py直接引用package_test包,是否可以执行呢?
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
sys.path.append(BASE_DIR)
import package_test
package_test.test1.test()
执行报错
ModuleNotFoundError: No module named 'test1'
因为import package_test 这一步是执行package_test目录下的init.py文件,而这个文件是空的
修改init.py文件,从当前目录下,导入test1模块
这个 点 表示相对于init.py文件的路径。
from . import test1
再次执行main.py
执行输出
in the test1
再深层次的目录调用,目录结果如下:
python_script/
├── day4
│ └── test.py
└── day5
└── package_test
├── init.py
└── test1.py
day5的代码,同上,没改动
test.py需要调用test1.py,那么需要把python_script目录加到环境变量即可
修改day4下的test.py文件
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
print(BASE_DIR)
执行输出
E:\python_script
加载到环境变量
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
sys.path.append(BASE_DIR)
from day5 import package_test
package_test.test1.test()
执行输出
in the test1
注意下面这行代码
from day5 import package_test
day5表示python_script目录下的day5
导入优化
语法:
from 模块名 import 函数或变量名
举个例子,目录结构如下:
test4/
├── module_test.py
└── test.py
module_test.py内容如下:
def test():
print('in the test')
test.py内容如下:
import module_test
def logger():
module_test.test()
print('in the logger')
def search():
module_test.test()
print('in the search')
假设有N个函数在调用module_test.test()
...
logger()
执行输出
in the test
in the logger
module_test.test()在执行的时候,先找到module_test模块,再从里面检索test函数是否存在。
那么每执行一次,就要先找模块,再找函数,重复劳动,效率很低。
为了解决这个问题,就是在导入模块的时候,不让它找就可以了
import module_test
改成
from module_test import test
就可以了。
下面的执行方法module_test.test()改成test() 就可以了,完整代码如下
!/usr/bin/env python
coding: utf-8
author = 'www.py3study.com'
from module_test import test
def logger():
test()
print('in the logger')
def search():
test()
print('in the search')
....
logger()
执行输出
in the test
in the logger
这种方法,可以使代码执行的更快
为了避免函数重名,可以在导入的时候,起别名
from module_test import test as mod_test