# 13.模块

**模块** 是一个包含所有你定义的函数和变量的文件，其后缀名是`.py`。模块可以被别的程序引入，以使用该模块中的函数等功能。

## 1. 引入模块 import

`import` 关键字用于引入模块

```py
import requests 
```

**Tip**: 不论 import 调用多少回， 同一个模块只会被引入一次

`from ... import ...` 语句用于从模块中引入部分代码，而不引入整个模块

```py
# 从 fibo 模块中引入 fib，fib2 函数 
from fibo import fib, fib2
fib(500)
```

### 搜索路径

当使用`import`关键字来引入模块时，会按照搜索路径指定的目录逐个去查询是否有匹配的模块名。

**搜索路径** 是在Python编译或安装的时候确定的，安装新的库应该也会修改。

搜索路径被存储在sys模块中的path变量。

![](https://pic.existorlive.cn/202112230047970.png)

搜索路径一般包括**当前执行脚本目录**，**python解释器的安装目录**

## 2. 深入模块

模块除了方法定义，**还可以包括可执行的代码。这些代码一般用来初始化这个模块。这些代码只有在第一次被导入时才会被执行**。

每个模块有各自独立的**符号表**，在模块内部为所有的函数当作全局符号表来使用。

模块是可以导入其他模块的，被导入的模块的名称将被放入当前操作的模块的符号表中。另外还可以使用 import 直接把模块内（函数，变量的）名称导入到当前操作模块。

```py
# 导入模块中所有的名字
import requests 

# 导入模块内的 fib，fib2
from fibo import fib, fib2

# 导入模块内的所有名字
from fibo import *
```

### 2.1 **name** 属性

一个模块被另一个程序第一次引入时，其主程序将运行。如果我们想在模块被引入时，模块中的某一程序块不执行，我们可以用`__name__`属性来使该程序块仅在该模块自身运行时执行。

```py
#!/usr/bin/python3
# Filename: using_name.py

if __name__ == '__main__':
   print('程序自身在运行')
else:
   print('我来自另一模块')
```

> 每个模块都有一个\_\_name\_\_属性，当其值是'**main**'时，表明该模块自身在运行，否则是被引入。

### 2.2 dir() 函数

内置函数 `dir()` 可以输出模块内定义的所有名称

```py
import sys
dir(sys)
```

![](https://pic.existorlive.cn/202112230106834.png)

## 3. 包

包是一种管理 Python 模块命名空间的形式，采用"点模块名称"。 一个包中可以包含多个模块。\
比如一个模块的名称是 A.B， 那么他表示一个包 A中的子模块 B 。

包的目录下必须包含一个 `__init_.py` 文件，

![](https://pic.existorlive.cn/202112230114238.png)

如图，`concurrent`包中有一个子包`futures`, `futures`包中包含`process`,`thread`等模块

## 总结

* 每个模块都有独立的符号表，引入模块就是将其他模块的名称引入当前模块的符号表

```py
# 导入模块中所有的名字
import requests 

# 导入模块内的 fib，fib2
from fibo import fib, fib2
```

* 包是管理模块的目录，目录下必须有`__init__.py` 文件
*
