模块及常见内置模块
模块简介
模块是一系列功能的集合。可以是一个py文件,一个集合多个py文件的文件夹,python2需要在文件夹中有一个__init__.py文件。
使用模块能够提高编程效率,而不必再花费大量时间编写已经有高人实现的功能代码。
模块有python内置的,第三方的,自定义的。
import
模块的使用需要导入,我们借助关键字import导入模块。
# import 模块名称(文件名)
# 通过 模块名.名称 使用模块中的变量或函数等
'''
import导入多次只执行一次
import导入流程:
1.运行导入文件生成该文件全局名称空间
2.运行导入的模块文件
3.产生模块文件的全局名称空间,将模块文件下的名字都存储再名称空间中
4.再导入文件中产生模块名指向模块的全局名称空间
'''
from...import...
模块的导入还能使用from...import...句式。
# from 模块名称 import 模块中变量或函数名
# 代码中直接使用import后的变量或函数
'''
from...import... 导入多次只执行一次
from...import...导入流程:
1.运行导入文件生成该文件全局名称空间
2.运行导入的模块文件,产生模块的全局名称空间
3.将模块文件下的名字都存储再名称空间中
4.再导入文件中产生名字指向模块名称空间中的名字
'''
导入模块扩展用法
- 别名
# 为导入的test模块取别名t
import test as t
# 为从test模块中导入的name_test取别名nt
from test import name_test as nt
- 连续导入
# 连续导入多个模块
import test1,test2,test3
# 从模块中连续导入多个名称
from test import 名称1,名称2,名称3
- 通用导入
# 把test模块中所有的名称都导入
from test import *
# all方法指定了此模块能被导出的名称 __all__('get','set')
判断文件类型
__name__判断是执行文件还是被当作模块文件导入,执行文件返回__main__,被当作模块导入执行时返回模块名。
循环导入
在导入模块的过程中,两个模块都需要先导入对方而发生错误。
首先循环导入的发生只能说明代码的不规范,我们不应该出现此情况,而此时只是在错误的情况下的解决方案。
- 调换顺序
将彼此导入的句式放在代码的最后 - 函数形式
将导入的句式放入函数体代码 等待所有的名字加载完毕之后再调用
模块导入顺序
- 在内存中查找
- 在内置模块中查找
- 在sys.path系统路径中查找(当前执行文件目录下)
如果都没有则报错。
ps: 自定义的模块名一定不要与内置模块名冲突。
绝对导入和相对导入
- 绝对导入
始终以执行文件所在的sys.path中查找模块。
sys.path返回的路径是当前执行文件的目录,而pycharm也为我们把根目录路径加入到了sys.path中,我们可以用这个根目录找到此目录下的所有包及模块。 - 相对导入
相对导入中使用.表示当前目录下,..表示上级目录。它打破始终以执行文件为准的规则,只注重两个文件之间的位置关系。但是相对导入只能在模块文件中使用,不能在执行文件中使用。
软件开发目录规范
- bin 存放一系列启动文件目录(启动文件很少时可以放根目录下)
start.py 启动文件 - db
userinfo.txt 存放用户数据 - core
src.py 存放项目核心业务逻辑代码 - conf 配置文件目录
settings.py 存放项目中一些配置常量 - lib 公共工具目录
common.py 公共工具模块文件 - log 日志目录
log.txt 日志文件 - requirments.txt 软件开发需要下载的第三方包及版本
- README.md 项目介绍、使用方法
pytho内置模块之collections
namedtuple(具名元组)
from collections import namedtuple
Point = namedtuple('Point',['x','y'])
point = Point(1,4)
print(point) # Point(x=1, y=4)
print(point.x) # 1
print(point.y) # 4
deque(双端队列)
from collections import deque
deque1 = deque([1])
deque1.append(2)
deque1.appendleft(2)
print(deque1.pop()) # 2
print(deque1.popleft()) # 2
print(deque1) # deque([1])
OrderedDict(有序字典)
from collections import OrderedDict
od1 = OrderedDict([('name','xie'),('age',18)])
print(od1) # OrderedDict([('name', 'xie'), ('age', 18)])
od1['gender'] = 'male'
print(od1) # OrderedDict([('name', 'xie'), ('age', 18), ('gender', 'male')])
defaultdict(默认值字典)
from collections import defaultdict
# 将l列表中大于60放入字典k1对应的列表,否则放入k2中。
l = [43,11,86,834,21,54,98]
dt = defaultdict(list)
for i in l:
if i > 66:
dt['k1'].append(i)
else:
dt['k2'].append(i)
print(dt) # defaultdict(<class 'list'>, {'k2': [43, 11, 21, 54], 'k1': [86, 834, 98]})
Counter(计数器)
from collections import Counter
str1 = 'dnagapegnavajiwruvmglcmoaie'
'''
ret = {}
for i in str1:
if i in ret:
ret[i] += 1
else:
ret[i] = 1
print(ret)
'''
print(Counter(str1))
# Counter({'a': 5, 'g': 3, 'n': 2, 'e': 2, 'v': 2, 'i': 2, 'm': 2, 'd': 1, 'p': 1, 'j': 1, 'w': 1, 'r': 1, 'u': 1, 'l': 1, 'c': 1, 'o': 1})
pytho内置模块之time
前面我们就用到了几个time模块的方法,如
time.sleep() # 让程序‘停止’设定的秒数
time.time() # 返回从1970.1.1到现在经历的描述
首先,时间通常有三种表现形式,三种形式可以相互转化。
1.时间戳
时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行type(time.time()),返回的是float类型。
2.格式化时间
import time
print(time.strftime('%Y-%m-%d')) # 2021-11-25
print(time.strftime('%Y-%m-%d %H:%M:%S')) # 2021-11-25 16:49:46
print(time.strftime('%Y-%m-%d %X')) # 2021-11-25 16:49:46
'''
格式化的时间字符串
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
'''
3.结构化时间
struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)
| 索引 | 属性 | 值 |
|---|---|---|
| 0 | tm_year | 比如2021 |
| 1 | tm_mon | 1 - 12 |
| 2 | tm_mday | 1 - 31 |
| 3 | tm_hour | 0 - 23 |
| 4 | tm_min | 0 - 59 |
| 5 | tm_sec | 0 - 60 |
| 6 | tm_wday | 0 - 6(0表示周一) |
| 7 | tm_yday | 1 - 366 |
| 8 | tm_isdst | 默认为0 |
import time
# localtime将时间戳转化为当前时区的结构化时间数据
print(time.localtime())
# time.struct_time(tm_year=2021, tm_mon=11, tm_mday=25, tm_hour=17, tm_min=5, tm_sec=16, tm_wday=3, tm_yday=329, tm_isdst=0)
time.struct_time(tm_year=2021, tm_mon=11, tm_mday=25, tm_hour=17, tm_min=5, tm_sec=16, tm_wday=3, tm_yday=329, tm_isdst=0)
pytho内置模块之datetime
import datetime
# 自定义日期
print(datetime.date(1997, 12, 6)) # 1997-12-06
# 获取当前日期
print(datetime.date.today()) #2021-11-25
# 获取当前年日月 时分秒
print(datetime.datetime.today()) # 2021-11-25 17:11:11.607572
print(datetime.datetime.now()) # 2021-11-25 17:11:11.607572
# 用datetime对象获得特定的年、月、日等
ret = datetime.datetime.now()
print(ret.year) # 2021
print(ret.month) # 11
print(ret.day) # 25
print(ret.weekday()) # 3 返回0-6 表示周一到周日
print(ret.isoweekday()) # 4 返回1-7 表示周一到周日
# 时间差 timedelta
ctime = datetime.datetime.today() # 2021-11-25 17:21:22.106802
dtime = datetime.timedelta(days=1)
print(ctime - dtime) # 2021-11-24 17:21:22.106802
print(ctime + dtime) # 2021-11-26 17:21:22.106802
内置模块之random
python提供了获取随机数的模块random。
# random()方法返回0-1之间的小数
ret = random.random()
# randint(start,end)方法返回start到end之间的整数
ret = random.randint(1,10)
# uniform(start,end)方法返回start-end之间的小数
ret = random.uniform(112)
# choice(['1','2'])方法返回容器类型对象中任意一个元素
ret = random.choice(['xie','lin'])
# sample([1,2,3],1)方法返回容器类型对象中指定个数的元素
ret = random.sample(['xie','lin','san'],2)
# shuffle方法打乱容器类型对象中的元素排列
ret = random.shuffle([1,3,4,12,5])
# 获取n位数验证码
import random
def get_code(n):
code = []
for i in range(n):
upper = chr(random.randint(65, 90))
lower = chr(random.randint(97, 122))
num = str(random.randint(0, 9))
selected = random.choice([upper, lower, num])
code.append(selected)
return ''.join(code)
内置模块之os
# 创建单级目录
os.path.mkdir('目录名')
# 创建多级目录
os.path.makedirs('目录1\目录2')
# 删除空目录 (多级目录无法删除)
os.path.rmdir('目录')
# 删除多目录,若目录为空递归删除上级目录
os.path.removedirs('目录1\目录2')
# 获得当前目录路径
BASE_PATH = os.path.dirname(__file__)
# 路径拼接
target_path = os.path.join(BASE_PATH,'目录或文件')
# 列举指定路径下所有目录及文件
dir_list = os.listdir('目录')
# 删除文件
os.remove('文件路径')
# 修改文件名称
os.rename('旧名称','新名称')
# 获取当前工作路径
os.getcwd()
# 切换路径
os.chdir('路径')
# 判断当前路径是否存在
os.path.exists('路径及文件')
# 判断当前路径是否是文件
os.path.isfile('文件')
# 判断当前路径是否是文件夹
os.path.isdir('路径')
# 获取文件大小(字节数)
os.path.getsize('文件')
内置模块之sys
import sys
# sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
# 获取Python解释程序的版本信息
sys.version
# 返回操作系统平台名称
sys.platform
# 返回终端执行py文件时传递的参数列表,第一个元素是程序本身路径
sys.argv
内置模块之序列化
什么叫序列化——将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。

import json
p = {'name':'xie','age':18,'gender':'male'}
# dumps方法将python字典序列化为json格式字符串
p_json = json.dumps(p)
print(p_json,type(p_json)) # {"name": "xie", "age": 18, "gender": "male"} <class 'str'>
# load方法将json格式字符串反序列化为python字典
new_p = json.loads(p_json)
print(new_p,type(new_p)) # {'name': 'xie', 'age': 18, 'gender': 'male'} <class 'dict'>
# PS:
# dump方法可以直接序列化数据写入文件,load方法可以直接反序列读取文件的数据。
# 数据中有中文时,需要设置ensure_ascii=False
'''
python类型序列化及反序列化与json对应表
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
'''
python模块之subprocess
res = subprocess.Popen('tasklist',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
print('stdout',res.stdout.read().decode('gbk')) # 获取正确命令执行之后的结果
print('stderr',res.stderr.read().decode('gbk')) # 获取错误命令执行之后的结果
# PS: China地区 windows电脑内部编码默认为GBK
# import 模块名称(文件名)
# 通过 模块名.名称 使用模块中的变量或函数等
'''
import导入多次只执行一次
import导入流程:
1.运行导入文件生成该文件全局名称空间
2.运行导入的模块文件
3.产生模块文件的全局名称空间,将模块文件下的名字都存储再名称空间中
4.再导入文件中产生模块名指向模块的全局名称空间
'''
内置模块之hashlib
对于像密码这样的数据,使用明文存储会有一些风险,所以需要一些算法加密这些数据,并且这种算法是不可逆推的,明文数据只有用户自身知道。python的内置模块提供了hashlib用于处理数据加密的操作。

import hashlib
md5 = hashlib.md5()
md5.update(b'123')
print(md5.hexdigest()) # 202cb962ac59075b964b07152d234b70
# ----------------------------------------------
# 明文拆开分段使用update,加密字符结果相同
md5.update(b'a123')
print(md5.hexdigest()) # 80c9ef0fb86369cd25f90af27ef53a9e
md5.update(r'a')
md5.update(r'123')
print(md5.hexdigest()) # 80c9ef0fb86369cd25f90af27ef53a9e
# ----------------------------------------------
# 加密算法越复杂生成的加密字符越长
sha256 = hashlib.sha256()
sha256.update(b'123')
print(sha256.hexdigest()) # a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
# ----------------------------------------------
# 加盐处理(在破解者不知道salt情况下,相当于给了干扰)
salt = b'sun'
md5.update(b'a123')
md5.update(salt)
print(md5.hexdigest()) # fb355750fe871eedda63e41ef5722c6b
# 动态加盐
time = str(time.time()).encode('utf8')
md5.update(b'123')
md5.update(time)
print(md5.hexdigest()) # af29de72f63a1490e86dd8ccf44b2ba0
加密处理也能够使用在检验文件一致性中来保证文件未被不良程序修改。对于大型文件可以使用切片分段的来加密一些数据比对下载前后是否改变。
内置模块之logging

日志分五个级别,默认是warining级别(30):
- debug 10
- info 20
- warning 30
- error 40
- critical 50
logging基本使用
import logging
# 日志级别
# logging.debug('debug级别') # 10
# logging.info('info级别') # 20
# logging.warning('warning级别') # 30
# logging.error('error级别') # 40
# logging.critical('critical级别') # 50
# 简单使用
file_handler = logging.FileHandler(filename='log.log', mode='a', encoding='utf-8')
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
handlers=[file_handler,],
level=logging.ERROR
)
logging.error('程序错误...')
日志模块详细介绍
import logging
# 1.创建logger对象
logger = logging.getLogger('mylogger')
# 2.fliter对象:负责过滤日志(直接忽略)
# 3.handler对象:负责日志产生位置
h1 = logging.FileHandler('log1.log',encoding='utf8') # 产生日志到文件
h2 = logging.FileHandler('log2.log',encoding='utf8') # 产生日志到文件
h3 = logging.StreamHandler() # 产生终端输出日志
# 4.formatter对象:负责日志的格式
fm1 = logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p')
fm2 = logging.Formatter(
fmt='%(asctime)s - %(name)s %(message)s',
datefmt='%Y-%m-%d')
# 5.绑定handler对象
logger.addHandler(h1)
logger.addHandler(h2)
logger.addHandler(h3)
# 6.绑定formatter对象
hd1.setFormatter(fm1)
hd2.setFormatter(fm2)
hd3.setFormatter(fm1)
# 7.设置日志等级
logger.setLevel(30)
# 8.记录日志
logger.debug('Long may the sunshine!')
logging字典配置
import logging
import logging.config
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d][%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
logfile_path = 'log.log' # 配置文件路径
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {}, # 过滤日志
'handlers': {
#打印到终端的日志
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
#打印到文件的日志,收集info及以上的日志
'default': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
'formatter': 'standard',
'filename': logfile_path, # 日志文件
'maxBytes': 1024*1024*5, # 日志大小 5M
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
#logging.getLogger(__name__)拿到的logger配置 空字符串作为键 能够兼容所有的日志
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG',
'propagate': True, # 向上(更高level的logger)传递
}, # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
},
}
# 使用配置字典
logging.config.dictConfig(LOGGING_DIC) # 自动加载字典中的配置
logger1 = logging.getLogger('xxx')
logger1.debug('完成了...')

第三方模块
python提供pip指令下载第三方的模块,如 pip3 install 模块名。
由于pip默认从国外的仓库下载你所需要的模块,有时候下载速度会很慢,我们可以使用-i 仓库地址指定下载的仓库地址,如 pip3 install 模块名 -i 仓库地址。
pycharm中在settings -> project -> project interprter可以管理源地址,添加新的地址后搜索模块会显示新地址仓库中的。

浙公网安备 33010602011771号