第六章 模块

到目前为止我们所有写的代码都在一个文件中,

当我们的程序规模变大时,把所有的功能都放在一个文件中变得不容易维护了

所以我们需要模块,模块和函数一样,是一种封装,让我们把可能会被重复使用的功能封装起来

使用的时候直接拿来用就好了。和函数,类一样,分为定义和使用。

简单来说模块就是一个py文件。

python中的模块可以分为三种 

  • 标准模块,python语言提供给我们的,可以直接用
  • 第三方模块,需要我们下载安装,再使用
  • 我们自己定义一个模块,自己使用,也可以让别人用

无论哪一种模块,本质就是一个py文件

6.1 自定义模块和包

自定义一个模块就是自己写一个py文件,我们可以把一类相关的功能放在一个py文件中

# log.py
from datetime import datetime
def log(msg):
    print('%s - INFO: %s' % (datetime.now().strftime("%Y-%m-%d %H:%M:%S"), msg))
    
log('日志消息测试')   
#main.py

import log
log.log("main文件打印消息")
import log
2020-07-23 16:26:12 - INFO: 日志消息测试
2020-07-23 16:26:12 - INFO: main文件打印消息

自己定义一个log.py文件就是一个模块 ,我们在main.py模块中使用import导入,导入后就可以通过. 来引用log模块定义的变量(函数即变量,类也是变量)

使用import在导入模块时,第一次导入会执行模块文件,此后再次导入都不会执行了

如果不想每次使用模块名加 . 来访问模块中的变量,可以使用from语句,指定导入模块中的变量

# main.py
from log import log

log("使用from语句导入log")
# main.py
from log import *
log("全部导入")

 

导入模块或从模块中导入变量时要注意,引入的变量到当前作用域中,会覆盖当前作用域中的同名变量

当然也有可能被当前作用域的同名变量所覆盖,所以要记住,python是从上到下执行的,后面定义的永远会覆盖前面定义的同名变量

# main.py
# 当前作用域中的同名变量会被覆盖 

log = '我是当前作用域中的变量'

from log import log
log("我是导入的变量")
# main.py
# 被当前作用域中的同名变量覆盖 

from log import log
log = '我是当前作用域中的变量'
log("我是导入的变量")

模块是一个py文件,

包是一个文件夹, 在文件夹中放入__init__.py文件,文件夹就变成了一个包

包其实也是一种模块,只不过一个包里可以包含若干个其它的模块,就是把模块放到包的文件夹里

我们可以通过目录名导入包,包的内容就是__init__.py文件的内容 

也可以通过包名.模块名的方式导入包下面的一个模块 

#
# package/__init__.py

from datetime import datetime
def package_log(msg):
    print('%s - PACKAGE: %s' % (datetime.now().strftime("%Y-%m-%d %H:%M:%S"), msg))
    
package_log('包里的日志消息')   
# package/log.py
from datetime import datetime
def log(msg):
    print('%s - LOG: %s' % (datetime.now().strftime("%Y-%m-%d %H:%M:%S"), msg))
    
log('包中模块的日志消息')   
# main.py
import package
import package.log
from package import log
from package.log import log

注意,无论是导入包,还是导入包下面的模块,都会执行包里的内容

 

虽然我们导入的时候 可以执行模块或包中的代码,但是一个提供给别人使用的模块,最好只包括定义的语句,不要有过多的执行语句 

 

 

6.2 导入顺序

目前为止我们的模块和包和我们的代码都放在同一个目录里

如果我们把模块和包放在电脑其它的目录里,导入包和模块的代码放在另一个目录里

导入时就会提示找不到模块和包

导入模块和包是有一个搜索顺序的,按照顺序搜索是否有对应的包和模块,搜索到之后就导入成功,如果搜索不到就报错

导入的顺序是按照一个目录列表来查找的,想查看有哪些目录,我们可以通过以下代码来看

# 导入顺序
import sys
from pprint import pprint
pprint(sys.path)
['/Users/mac/PycharmProjects/jupyter',
 '/Users/mac/PycharmProjects/jupyter',
 '/Users/mac/PycharmProjects/auto-test',
 '/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python37.zip',
 '/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
 '/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload',
 '',
 '/usr/local/lib/python3.7/site-packages',
 '/usr/local/lib/python3.7/site-packages/aeosa',
 '/usr/local/lib/python3.7/site-packages/IPython/extensions',
 '/Users/mac/.ipython']

我们可以把我们自己定义的模块和包放在上面目录的任何一个位置,这样我们无论在哪里写代码导入都可以导入包和模块 

每个人的电脑环境不一样,所以上面的目录列表可能都不相同

但肯定都会有一个site-packages目录,成熟的模块放在这个目录下是最合适的,但要注意不要与产生名字冲突,

很多第三方安装的模块也会放在这个目录 下面

 

把模块放在目录上面的目录列表是一种方法

另外我们也可以在操作系统中配置环境变量的方式,增加搜索目录 

其实也可以直接把目录添加到sys.path列表中,不过这种方法不是特别推荐 

 

系统中配置环境变量PYTHONPATH,把想要添加的搜索目录配置到这个变量中,python搜索模块的路径就会增加这些目录 

 

 

6.3 模块的属性

python中一切都是对象,很显然,模块也是对象 

模块用.来访问他的属性,实际上模块中定义的变量都是模块的属性,包括函数,变量,类

我们学几个特殊的属性

  • __doc__

就是模块的帮助文档,模块的帮助文档也是模块中第一个字符串,用来描述模块的功能

可以直接访问,也可以通过help查看

 

  • __file__

模块文件的实际路径,可以直接访问

 

  • __name__

模块文件运行时的名字,如果模块是被导入的,名字是None

如果模块是由解释器运行的,名字是__main__

利用这个,我们可以把模块的调试代码 放在这样一个语句块下

if __name__ == '__main__':
    print("测试代码在这里")

这样,只有我们写模块的时候 调试的时候,会让解释器直接运行模块 ,就会执行测试代码

如果我们的模块是被其它模块导入使用的,__name__是None就不会执行测试代码 

 

  • __all__

__all__我们可以自定义,这是一个列表,其中可以放入我们希望别人使用的模块变量

这样别人在执行

from 模块 import *

 

这样不会导入其它变量,只会导入__all__列表中的变量

 

6.4 一些内置模块

6.4.1 sys

常用变量 含义
argv 命令行参数
path 模块导入路径
stdin 标准输入
stdout 标准输出
stderr 标准错误
platform  操作系统平台

 

6.4.2 os

常用变量 含义
environ 环境变量字典
system(command) 执行操作系统命令
linesep 换行符
path.split 分割路径
path.join 拼接路径 
listdir 列出目录下的文件
remove 删除文件
mkdir 创建目录
walk 遍历目录和文件

 

其中walk值得说一下,walk传入一个路径,返回一个迭代器,我们可以通过一个for循环遍历一个目录下的所有文件 

非常实用的一个方法

import os
for root, dirs, files in os.walk('/Users/mac/PycharmProjects/python_test'):
    for file in files:
        print(os.path.join(root, file))

root是当前文件的目录,dirs是当前文件目录下的目录列表,files是当前文件目录下的文件列表

 

6.4.3 time和datetime

time模块常用的两个,一个是time.time 返回的是一个时间戳,表示从1970年1月1日0时0分0秒到现在的秒数

time.sleep(sec)可以让程序休眠指定的秒数

datetime模块,主要处理日期和时间 

# time  datetime
import time
print(time.time())
time.sleep(1)
print(time.time())

from datetime import datetime, timedelta
print(datetime.now())
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
print(datetime.utcnow())
print(datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"))

#处理日期偏移
print(datetime.now() + timedelta(days=1, seconds=30, minutes=30))

print((datetime.now() - datetime(year=2020, month=7, day=20)).days)

datetime类可以构建一个日期时间对象,timedelta可以构造一个日期时间的间隔

datetime对象之间可以相减,得到日期时间间隔

datetime和日期时间间隔之间可以加减,算出一个新的日期 

 

6.4.4 random

random主要用来处理随机相关的方法

# random
import random

print('产生1~100之间的随机数', random.randint(1, 100))
print('产生0~1 之间的随机小数', random.random())
print('从列表中随机选择一个元素', random.choice([x for x in range(1,20)]))
print('从列表中随机选择三个元素', random.sample([x for x in range(1,20)], 3))

6.4.5 re

re是匹配字符串的一个模块,使用re模块必须先了解正则表达式

正则表达是一种字符串匹配的标准,几乎所有的语言都会支持

python中就是通过 re模块来支持正则表达式

 

模式 含义
. 匹配任意字符,除换行符\r,\n
[xyz] 匹配中括号中的任意一个字符
x|y 匹配x或y
[^xyz] 匹配不包含中括号中的字符
[a-z] 匹配小写字符
[A-Z] 匹配大写字符
[0-9] 匹配数字
[A-Za-z0-9] 匹配大小写字母和数字
\d 匹配任意数字
\D 匹配任意非数字 
\s 匹配任意不可见字符
^ 从行首开始匹配
$ 人行尾匹配
* 匹配前面的子表达式0次或任意次
+ 匹配前面的子表达式1次或任意次
匹配前面的子表达式0次或1次
{n} 匹配前面的子表达式n次
{n,} 匹配前面的子表达式至少n次
{n,m} 匹配前面的子表达式n到m次
\ 转义

 

 

6.4.6 pickle存储对象

import pickle
l = [1,2,3]
f = open('pickle.sav', 'wb')
print(pickle.dump(l, f))
f.close()
f = open('pickle.sav', 'rb')
l = pickle.load(f)
print(l)

6.5.7 JSON 序列化

import json

employee = {
    'name' : '王富贵',
    'age' : 18,
    'gender': '',
    'address': "深圳市宝安区西乡街道",
    'marry' : False,
    'hobby' : ['冲浪', '翻船']

}

s = json.dumps(employee)
print(s)

wfg = json.loads(s)
print(wfg)

 

 

 

 

6.5 第三方库

安装第三方库就使用pip命令

pip list
pip install
pip uninstall
pip freeze > requirements.txt
pip install -r requirements.txt

6.6 虚拟环境

使用虚拟环境是为了隔离不同项目之间的Python

创建虚拟环境

Python3 内置了venv模块,首先创建项目目录,进入目录后,执行

python3 -m venv 虚拟名

 

激活虚拟环境

在开始工作前,先要激活相应的虚拟环境:

windows

scripts/activate

 

linux

.  虚拟目录/bin/activate

 

激活后,你的终端提示符会显示虚拟环境的名称。

 

 

6.7 编码规范

PEP8

posted @ 2020-07-23 17:38  人不知所  阅读(101)  评论(0)    收藏  举报