Ⅰtime模块
【1】表示时间的三种方式
# 【1】时间戳表示时间 : 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
# 我们当时给函数计时 两次时间戳相减 得到了消耗的总时间
# 【2】元组(struct_time) (年,月,日,时,分,秒,毫秒,微妙)
# 【3】格式化的时间字符串 xx年-xx月-xx日 时:分:秒
# 1.方法
1.time.sleep(secs)
推迟指定的时间运行,单位为秒
ps:该方法贯穿前后
2.time.time()
获取当前时间戳
# 2.三种用于表达时间的格式(彼此之间可以转换
1.时间戳(time.time())
距离1970年1月1日0时0分0秒至此相差的秒数
2.结构化时间(time.strftime('%y-%m-%d %H:%M:%S'))
该时间类型主要是给计算机看的,人看起来不太方便
3.格式化时间(time.strftime())
人最容易接受间格式 2020/10/28 11:11:11
【2】时间类型的转换
格式化时间 <==> 结构化时间 <==> 时间戳
ps:UTC时间比国内区域时间早八小时(时区划分)
# 时间戳<-->结构化时间
gmtime
localtime
# 结构化时间<-->格式化时间
strftime
strptime
(1) 导入时间模块
import time
(2) 时间戳
# (1)生成时间戳
import time
time_str = time.time()
print(time_str) # 1713489632.6055946
# # 去掉多余的小数
import time
time_str = time.time()
print(int(time_str)) # 1713489632
# (2)时间戳转换为时间元组
# 国际时间
import time
time_tuple = time.gmtime(time.time())
print(time_tuple) # time.struct_time(tm_year=2024, tm_mon=4, tm_mday=19, tm_hour=1, tm_min=21, tm_sec=36, tm_wday=4, tm_yday=110, tm_isdst=0)
# 本地时间
import time
time_tuple = time.localtime(time.time())
print(time_tuple) # time.struct_time(tm_year=2024, tm_mon=4, tm_mday=19, tm_hour=9, tm_min=23, tm_sec=0, tm_wday=4, tm_yday=110, tm_isdst=0)
# (3)转换为时间字符串
# 转换时间的格式在 strftime 里面
import time
time_now = time.strftime('%Y-%m-%d %H:%M:%S')
time_now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
print(time_now) # 2024-04-19 09:25:13
time_now = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime())
print(time_now) # 2024-04-19 01:25:00
# 在里面的参数 ,后面加不加无所谓
# (4)转换为时间元组
date_time = time.localtime()
print(date_time) # time.struct_time(tm_year=2024, tm_mon=4, tm_mday=19, tm_hour=20, tm_min=31, tm_sec=36, tm_wday=4, tm_yday=110, tm_isdst=0)
# 从时间元组中获取出指定的属性
# 取出年月日时分秒
print(date_time.tm_year) # 当前年份
print(date_time.tm_mon) # 当前月份
print(date_time.tm_mday) # 当前日
print(date_time.tm_wday) # 当前周
print(date_time.tm_yday) # 当前天数 在一年中的第 x 天
print(date_time[-1]) # 是否是夏令时 默认为0
【3】结构化时间
(1) 时间戳转换
import time
time_str = time.time()
time_str = time.localtime(time_str)
time_str = time.mktime(time_str)
print(time_str) # 1713530083.0
(2) 结构化输出时间
time.strftime() : 格式化输出当前时间
(3) 将字符串的时间格式转换为时间元组
time_str = time.strptime("2023-11-24", "%Y-%m-%d")
print(time_str) # time.struct_time(tm_year=2023, tm_mon=11, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=328, tm_isdst=-1)
time_local = time.strptime("11/24/2023", "%m/%d/%Y")
print(time_local) # time.struct_time(tm_year=2023, tm_mon=11, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=328, tm_isdst=-1)
time_local = time.strptime("11:24:2023", "%m:%d:%Y")
print(time_local) # time.struct_time(tm_year=2023, tm_mon=11, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=328, tm_isdst=-1)
(4) 将时间元组转换为 国际时间格式
import time
time_str = time.asctime(time.localtime(time.time()))
print(time_str)
# Fri Apr 19 20:39:20 2024
time_local = time.asctime()
print(time_local)
# Fri Apr 19 20:39:20 2024
time_str = time.ctime(time.time())
print(time_str)
# Fri Apr 19 20:39:20 2024
time_local = time.ctime()
print(time_local)
# Fri Apr 19 20:39:20 2024
【4】总结
time.time() 生成时间戳
time.sleep() 随机睡眠多长时间
time.strftime() 格式化输出当前时间
time.strptime() 将时间字符串格式转换为时间元组
time.localtime() 拿到当前时间的时间元组格式
Ⅱ datetime模块
date 意思就是年月日
datetime 意思就是年月日 时分秒
【1】导入模块
import datetime
【2】自定义日期并格式化
(1) 根据时间日期生成指定的格式
import datetime
time_str = datetime.date(2020,10,28)
print(time_str) # 2020-10-28
(2) 获取本地时间
import datetime
print(datetime.date.today())
print(datetime.datetime.today().year)
print(datetime.datetime.today().month)
print(datetime.datetime.today().day)
print(datetime.datetime.today().hour)
print(datetime.datetime.today().minute)
print(datetime.datetime.today().second)
print(datetime.datetime.today().weekday()) # 4 0是周一 6是周日
print(datetime.datetime.today().isoweekday()) # 5 1是周一 7是周日
(3) timedelta对象(时间差)
""" 时间差 """"
# 作用:对时间进行推迟和提前
import datetime
now_day = datetime.date.today()
now_days = datetime.datetime.now()
print(now_day) # 2024-04-19
print(now_days) # 2024-04-19 21:29:34.533900
# 生成一个时间日期对象
time_change = datetime.timedelta(days=8)
print(now_day + time_change) # 2024-04-27
print(now_day - time_change) # 2024-04-11
'''
针对时间计算的公式
日期对象 = 日期对象 +/- timedelta对象
timedelta对象 = 日期对象 +/- 日期对象
'''
# 用来计算自己的生日
# 日期对象 = 日期对象 +/- timedelta对象
# timedelta对象 = 日期对象 +/- 日期对象
import datetime
birthday = datetime.date(2023, 11, 24)
now_date = datetime.date.today()
today = datetime.date.today()
days = now_date - birthday
print('生日:{}'.format(birthday)) # 生日:2023-11-24
print('今天的日期:{}'.format(today)) # 今天的日期:2024-04-19
print('距离生日还有{}天'.format(days)) # 距离生日还有147 days, 0:00:00天
Ⅲ os 模块
'''该模块主要是跟操作系统交互的一个接口'''
# os 模块 可以操作本地的文件夹及文件
# 创建删除文件件/文件
# 执行本地的cmd命令
# 拼接路径
# __file__ 表示当前文件
【1】文件路径相关的操作
# 【1】获取当前文件所在的文件夹路径
import os
file_name = os.path.dirname(__file__)
print(file_name) # E:\pythonprojects
# 【2】获取当前文件所在的文件路径
import os
file_path = os.path.abspath(__file__)
print(file_path) # E:\pythonprojects\test.py
# 【3】判断当前文件路径是否存在 文件夹/文件
import os
file_name = os.path.dirname(__file__)
file_path = os.path.abspath(__file__)
print(os.path.exists(path=file_name)) # True
print(os.path.exists(path=file_path)) # True
# 【4】拼接文件路径
import os
# 检查当前脚本文件所在目录下的 data 子目录是否存在
file_name = os.path.dirname(__file__)
file_new = os.path.join(file_name, 'data')
print(os.path.exists(path=file_new)) # False
base_dir = 'silence'
exe_dir = 'day1.py'
'''拼接成py文件路径'''
print(base_dir + '\\' + exe_dir ) # silence\day1.py
# 【5】切割文件路径
# 是一个元组有两个元素,分别是(其他路径,最后一个文件名/文件夹名)
import os
file_name = os.path.dirname(__file__)
file_split = os.path.split(file_name)
print(file_split) # ('E:\\', 'pythonprojects')
import os
file_path = os.path.abspath(__file__)
file_split = os.path.split(file_path)
print(file_split) # ('E:\\pythonprojects', 'test.py')
# 【6】直接获取文件夹结尾路径
import os
file_name = os.path.dirname(__file__)
file_split = os.path.split(file_name)
file_name_basename = os.path.basename(file_name)
print(file_name_basename) # pythonprojects
import os
file_path = os.path.abspath(__file__)
file_split = os.path.split(file_path)
file_name_basename = os.path.basename(file_path)
print(file_name_basename) # test.py
# 【7】判断当前文件路径是否是文件夹 / 文件
import os
file_name = os.path.dirname(__file__)
file_split = os.path.split(file_name)
file_path = os.path.abspath(__file__)
file_split = os.path.split(file_path)
# 判断是否是文件
print(os.path.isfile(file_name)) # False
print(os.path.isfile(file_path)) # True
# 判断是否是文件夹
print(os.path.isdir(file_name)) # True
print(os.path.isdir(file_path)) # False
# 【8】判断当前路径是否是绝对路径
import os
file_name = os.path.dirname(__file__)
file_split = os.path.split(file_name)
file_path = os.path.abspath(__file__)
file_split = os.path.split(file_path)
path_one = './test.py'
print(os.path.isabs(path_one)) # False
print(os.path.isabs(file_path)) # True
# 【9】获取当前文件或目录
# active : 最后访问时间
import os
import time
file_path = os.path.abspath(__file__)
path_one = './test.py'
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.path.getatime(file_path)))) # 2024-04-21 14:54:54
print(time.localtime(os.path.getatime(path_one)))
# time.struct_time(tm_year=2024, tm_mon=4, tm_mday=21, tm_hour=14, tm_min=55, tm_sec=35, tm_wday=6, tm_yday=112, tm_isdst=0)
# create : 创建时间
import os
import time
file_name = os.path.dirname(__file__)
file_path = os.path.abspath(__file__)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.path.getctime(file_name)))) # 2024-03-26 19:17:06
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.path.getctime(file_path)))) # 2024-04-09 13:47:52
# modify : 修改时间
import os
import time
file_name = os.path.dirname(__file__)
file_path = os.path.abspath(__file__)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.path.getmtime(file_name)))) # 2024-04-21 15:05:45
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(os.path.getmtime(file_path)))) # 2024-04-21 15:05:45
# 【10】获取当前文件的大小
import os
file_name = os.path.dirname(__file__)
file_path = os.path.abspath(__file__)
print(os.path.getsize(file_name)) # 4096
print(os.path.getsize(file_path)) # 231
【2】文件和文件夹操作
# 【1】主动创建文件夹.mkdir (只能创建单级目录)
os.mkdir(r'aaa') # 使用相对路径,在执行当文件所在的路径下创建一个aaa文件夹
import os
# E:\pythonprojects
BASE_DIR = os.path.dirname(__file__)
# E:\pythonprojects\img
# 拼接一个新路径
img_path = os.path.join(BASE_DIR, 'img')
# 判断这个文件夹是否存在
print(os.path.exists(img_path)) # False
# 如果不存在 创建一个img文件夹
if not os.path.exists(img_path):
os.mkdir(img_path)
print(os.path.exists(img_path))
# 【2】创建多级文件夹.makedirs (支持创建多级目录,也可创建单级目录)
import os
# E:\pythonprojects
BASE_DIR = os.path.dirname(__file__)
# 拼接一个新路径
log_path = os.path.join(BASE_DIR, 'log', 'user_log', 'silence_log')
# 判断这个文件夹是否存在
print(os.path.exists(log_path))
if not os.path.exists(log_path):
os.makedirs(log_path)
print(os.path.exists(log_path))
# 例二
path = os.path.join(os.path.dirname(__file__), '1', '2', '3')
# E:\pythonprojects\1\2\3
print(os.path.exists(path))
os.makedirs(path, exist_ok=True)
print(os.path.exists(path))
# 【3】删除单级文件夹.rmdir
# 只能删除空的文件夹 即使文件夹内有空文件夹也不算空的
# E:\pythonprojects\img
print(os.path.exists(img_path))
os.rmdir(img_path)
print(os.path.exists(img_path))
# 【4】删除多级文件夹.removedirs
# 删除多级文件夹目录 路径一定是到最里面那一层并且每个文件夹必须是空的
log_path = os.path.join(BASE_DIR,'log')
print(os.path.exists(log_path))
os.removedirs(log_path)
print(os.path.exists(log_path))
# 【5】列出当前文件下的所有文件名.listdir
import os
BASE_DIR = os.path.dirname(__file__)
print(os.listdir(BASE_DIR))
# 【6】删除指定文件.remove
import os
BASE_DIR = os.path.dirname(__file__)
data_path = os.path.join(BASE_DIR,'data.py')
os.remove(data_path)
# 【7】给指定文件或文件夹重命名.rename
# 给两个绝对路径
# 一个是之前的绝对路径
# 一个是重名后的绝对路径
import os
BASE_DIR = os.path.dirname(__file__)
old_path = os.path.join(BASE_DIR,'img.py')
new_path = os.path.join(BASE_DIR,'new_img')
os.rename(old_path,new_path)
# 文件img.py被修改成了new_img
import os
BASE_DIR = os.path.dirname(__file__)
old_path = os.path.join(BASE_DIR,'old.img.py')
new_path = os.path.join(BASE_DIR,'new.img.py')
os.rename(old_path,new_path)
# 文件old.img.py被修改成了new.img.py
# 【8】获取当前文件 / 文件夹的详细信息 元信息 .stat
import os
BASE_DIR = os.path.dirname(__file__)
# print(os.path.dirname(__file__)) # 获取当前执行文件所在的绝对路径
# print(os.path.dirname(os.path.dirname(__file__))) # 每嵌套一层就是往上切换一层
new_path = os.path.join(BASE_DIR, 'new.json.py')
print(os.stat(BASE_DIR))
# os.stat_result(st_mode=16895, st_ino=562949953441342, st_dev=1523532733, st_nlink=1, st_uid=0, st_gid=0, st_size=4096, st_atime=1713686019, st_mtime=1713686010, st_ctime=1711451826)
print(os.stat(new_path))
# os.stat_result(st_mode=33206, st_ino=63894819713344392, st_dev=1523532733, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1713685591, st_mtime=1713685591, st_ctime=1713685591)
# 【9】获取当前路径.getcwd
import os
BASE_DIR = os.path.dirname(__file__)
print(os.getcwd()) # E:\pythonprojects
# linux ---> 获取当前路径
# 【10】切换切换路径.getcwd
change_path = os.path.join(os.path.dirname(BASE_DIR), 'test.py')
os.chdir(change_path)
print(os.getcwd())
【3】执行shell命令
# 执行cmd命令
print(os.system('dir'))
print(os.popen('ping www.baidu.com'))
【4】获取当前系统信息
# 输出操作系统特定的路径分隔符
# win \
# mac / linux /
print(os.sep) # \
# 输出当前平台使用的行终止符
print(os.linesep) #
# 输出用于分割文件路径的字符串
print(os.pathsep)# ;
# 输出字符串指示当前使用平台
print(os.name) # nt
# win下为 'nt'
# Linux下为 'posix'
【记住的重点】
# os.path.join() 拼接路径
# os.path.dirname(__file__) 获取当前文件所在的文件夹路径
# os.path.abspath(__file__)获取当前文件所在的文件路径
# os.path.exists() 判断路径是否存在
# os.mkdir() 创建单级文件夹
# os.makedirs() 创建多级文件夹
# os.makedirs(path, exist_ok=True) 自动创建不存在的多级文件夹路径
Ⅳ random模块
# random 模块
# 随机生成整数 / 小数 / 指定列表中某一个元素
import random
【1】随机生成小数
# 【1】默认区间的小数 是区间 0 - 1 之间的小数
import random
print(random.random()) # 0.5889875753098118
# 【2】指定区间 给定区间内的小数
import random
print(random.uniform(1, 3)) # 1.116857395495219
【2】随机生成整数
# 【1】指定区间的整数 给定区间内的整数
print(random.randint(1, 5)) # 3
# 【2】随机区间内的奇偶数
# 奇数:不能被2整除
# 偶数:能被2整除
print(random.randrange(1, 10, 2)) # 1 3 5 7 9
print(random.randrange(1, 10, 3)) # 1 4 7
【3】随机返回值
# 【1】返回一个元素
# 给定一个可迭代类型
num_list = [i for i in range(1, 10)]
num_list += ['a', 'b', 'c', 'd']
print(random.choice(num_list)) # 7
# 【2】一次性返回多个元素
# 默认是返回一个元素的列表
import random
num_list = [i for i in range(1, 10)]
num_list += ['a', 'b', 'c', 'd']
print(random.choices(num_list))
# 可以指定关键字 k 指定返回的列表中的元素个数
print(random.choices(num_list, k=3)) # [7, 9, 8]
print(random.sample(num_list, 3)) # [7, 'd', 8]
【4】打乱顺序
num_list = [i for i in range(1, 10)]
print(num_list) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 没有返回值,影响到的是原来的列表
random.shuffle(num_list)
print(num_list) # [5, 7, 6, 8, 1, 2, 3, 4, 9]
【5】随机生成验证码
# 随机大小写字母 + 随机数字
# 补充知识点 chr(数字) ---> 返回指定ASCII码对应的字符
# 做一个能生成 6 位的验证码
import random
def get_verify_code(n):
code = ''
for i in range(n):
random_int = str(random.randint(0, 9)) # 0-9之间的整数
random_upper = chr(random.randint(65, 90)) # A-Z之间的字母
random_lower = chr(random.randint(97, 122)) # a-z之间的字母
temp = random.choice([random_int, random_upper, random_lower])
code += temp
return code
res = get_verify_code(6)
print(res) # Fiv8zv
Ⅴ logging模块
# logging 模块 记录 log 记录日志的模块
import logging
import logging.config
import os
import sys
try:
# 想要给日志上色就安装这个模块
# pip install coloredlogs :::>>> 给日志上个色
import coloredlogs
except Exception as e:
if str(e) == "No module named 'coloredlogs'":
pass
# 自定义日志级别
CONSOLE_LOG_LEVEL = "INFO"
FILE_LOG_LEVEL = "DEBUG"
# 自定义日志格式
# 打印在文件里的格式:时间戳 + 线程名 + 线程ID + 任务ID + 发出日志调用的源文件名 + 发出日志调用的源代码行号 + 日志级别 + 日志消息正文
# [2023-06-04 15:16:05][MainThread:22896][task_id:root][调用.py:12][INFO][这是注册功能]
STANDARD_FORMAT = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d][%(levelname)s][%(message)s]'
# 打印在控制台的格式:日志级别 + 时间戳 + 发出日志调用的源文件名 + 发出日志调用的源代码行号 + 日志消息正文
# [INFO][2023-06-04 15:37:28,019][调用.py:12]这是注册功能
SIMPLE_FORMAT = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
'''
参数详解:
-1.%(asctime)s: 时间戳,表示记录时间
-2.%(threadName)s: 线程名称
-3.%(thread)d: 线程ID
-4.task_id:%(name)s: 任务ID,即日志记录器的名称
-5.%(filename)s: 发出日志调用的源文件名
-6.%(lineno)d: 发出日志调用的源代码行号
-7.%(levelname)s: 日志级别,如DEBUG、INFO、WARNING、ERROR、CRITICAL等
-8.%(message)s: 日志消息正文
'''
# 日志文件路径
BASE_DIR = os.path.dirname(__file__)
# os.getcwd() : 获取当前工作目录,即当前python脚本工作的目录路径
# 拼接日志文件路径 : 当前工作路径 + “logs”(日志文件路径)
LOG_PATH = os.path.join(BASE_DIR, "logs")
# OS模块 : 创建多层文件夹
# exist_ok=True 的意思是如果该目录已经存在,则不会抛出异常。
os.makedirs(LOG_PATH, exist_ok=True)
# log日志文件路径 : 路径文件夹路径 + 日志文件
LOG_FILE_PATH = os.path.join(LOG_PATH, 'Logs.log')
# 日志配置字典
LOGGING_DIC = {
# 日志版本
'version': 1,
# 表示是否要禁用已经存在的日志记录器(loggers)。
# 如果设为 False,则已经存在的日志记录器将不会被禁用,而是可以继续使用。
# 如果设为 True,则已经存在的日志记录器将会被禁用,不能再被使用。
'disable_existing_loggers': False,
# 格式化程序:用于将日志记录转换为字符串以便于处理和存储。
# 格式化程序定义了每个日志记录的输出格式,并可以包括日期、时间、日志级别和其他自定义信息。
'formatters': {
# 自定义格式一:年-月-日 时:分:秒
'standard': {
# 自定义日志格式 :时间戳 + 线程名 + 线程ID + 任务ID + 发出日志调用的源文件名 + 发出日志调用的源代码行号 + 日志级别 + 日志消息正文
# 这里要对应全局的 STANDARD_FORMAT 配置
'format': STANDARD_FORMAT,
# 时间戳格式:年-月-日 时:分:秒
'datefmt': '%Y-%m-%d %H:%M:%S' # 时间戳格式
},
# 自定义格式二:
'simple': {
# 自定义日志格式:# 日志级别 + 时间戳 + 发出日志调用的源文件名 + 发出日志调用的源代码行号 + 日志消息正文
# 这里要对应全局的 SIMPLE_FORMAT 配置
'format': SIMPLE_FORMAT
},
},
# 过滤器
'filters': {},
# 日志处理器
'handlers': {
# 自定义处理器名称 - 输出到控制台屏幕
'console': {
# 设置日志等级 为INFO
'level': CONSOLE_LOG_LEVEL,
# 表示该处理器将输出日志到流(stream):日志打印到控制台
'class': 'logging.StreamHandler',
# 日志打印格式:日志级别 + 时间戳 + 发出日志调用的源文件名 + 发出日志调用的源代码行号 + 日志消息正文
# 这里的配置要对应 formatters 中的 simple 配置
'formatter': 'simple'
},
# 自定义处理器名称 - 输出到文件
'default': {
# 自定义日志等级
'level': FILE_LOG_LEVEL,
# 标准输出到文件
'class': 'logging.handlers.RotatingFileHandler',
# 日志打印格式:年-月-日 时:分:秒
# 这里的配置要对应 formatters 中的 standard 配置
'formatter': 'standard',
# 这里 要注意声明配置文件输出端的文件路径
'filename': LOG_FILE_PATH,
# 限制文件大小:1024 * 1024 * 5 = 5242880,意味着这个变量的值是 5MB(兆字节)
'maxBytes': 1024 * 1024 * 5,
# 表示保留最近的5个日志文件备份。
# 当日志文件达到最大大小限制时,将会自动轮转并且保留最新的5个备份文件,以便查看先前的日志记录。
# 当日志文件达到最大大小限制时,会自动进行轮转,后续的文件名将会以数字进行命名,
# 例如,第一个备份文件将被重命名为原始日志文件名加上".1"的后缀,
# 第二个备份文件将被重命名为原始日志文件名加上“.2”的后缀,
# 以此类推,直到保留的备份数量达到设定的最大值。
'backupCount': 5,
# 日志存储文件格式
'encoding': 'utf-8',
},
},
# 日志记录器,用于记录应用程序的运行状态和错误信息。
'loggers': {
# 空字符串作为键 能够兼容所有的日志(当没有找到对应的日志记录器时默认使用此配置)
# 默认日志配置
'': {
# 日志处理器 类型:打印到控制台输出 + 写入本地日志文件
'handlers': ['default', 'console'],
# 日志等级 : DEBUG
'level': 'DEBUG',
# 默认情况下,当一个日志消息被发送到一个Logger对象且没有被处理时,该消息会被传递给它的父Logger对象,以便在更高层次上进行处理。
# 这个传递过程称为“传播(propagation)”,而propagate参数指定了是否要使日志消息向上传播。
# 将其设置为True表示应该传播消息到上一级的Logger对象;如果设置为False则不传播。
# 表示异常将会在程序中继续传播
# 也就是说,如果一个异常在当前的代码块中没有被处理,它将会在上级代码块或调用函数中继续向上传递,直到被某个代码块捕获或者程序退出。
# 这是 Python 中异常处理机制的默认行为。
# 如果将 'propagate' 设置为 False,则异常不会被传播,即使在上级代码块中没有处理异常的语句,程序也会忽略异常并继续执行。
'propagate': True,
},
},
}
def set_logging_color(name='', ):
# 初始化日志处理器 - 使用配置字典初始化日志处理器(将自定义配置加载到日志处理器中)
# logging.basicConfig(level=logging.WARNING)
logging.config.dictConfig(LOGGING_DIC)
# 实例化日志处理器对象 - 并赋予日志处理器等级
logger = logging.getLogger(name)
# 将logger对象传递给coloredlogs.install()函数,并执行该函数以安装彩色日志记录器,使日志信息在控制台上呈现为带有颜色的格式。
# 具体来说,该函数会使用ANSI转义序列在终端上输出日志级别、时间戳和消息等信息,并按日志级别使用不同的颜色来区分它们。这可以让日志信息更易于阅读和理解。
coloredlogs.install(logger=logger)
# 禁止日志消息向更高级别的父记录器(如果存在)传递。
# 通常情况下,当一个记录器发送一条日志消息时,该消息会被传递给其所有祖先记录器,直到传递到根记录器为止。但是,通过将logger.propagate设置为False,就可以阻止该记录器的消息向上层传递。
# 换句话说,该记录器的消息只会被发送到该记录器的处理程序(或子记录器)中,而不会传递给祖先记录器,即使祖先记录器的日志级别比该记录器要低。
# 这种方法通常适用于需要对特定记录器进行控制,并希望完全独立于其祖先记录器的情况。
# 确保 coloredlogs 不会将我们的日志事件传递给根 logger,这可以防止我们重复记录每个事件
logger.propagate = False
# 配置 日志颜色
# 这段代码定义了一个名为coloredFormatter的变量,并将其赋值为coloredlogs.ColoredFormatter。
# 这是一个Python库中的类,用于创建带有彩色日志级别和消息的格式化器。
# 该变量可以用作日志记录器或处理程序的格式化程序,以使日志输出更易于阅读和理解。
coloredFormatter = coloredlogs.ColoredFormatter(
# fmt表示格式字符串,它包含了一些占位符,用于在记录日志时动态地填充相关信息。
# [%(name)s]表示打印日志时将记录器的名称放在方括号内,其中name是一个变量名,将被记录器名称所替换。
# %(asctime)s表示打印日志时将时间戳(格式化为字符串)插入到消息中,其中asctime是时间的字符串表示形式。
# %(funcName)s表示打印日志时将函数名插入到消息中,其中funcName是函数的名称。
# %(lineno)-3d表示打印日志时将行号插入到消息中,并且将其格式化为3位数字,其中lineno表示行号。
# %(message)s表示打印日志时将消息本身插入到消息中。
# 综合起来,这个格式字符串将在记录日志时输出以下信息:记录器名称、时间戳、函数名称、行号和日志消息。
# 记录器名称 + 时间戳 + 函数名称 + 行号 + 日志消息
# [root] 2023-06-04 16:00:57 register 15 this is an info message
fmt='[%(name)s] %(asctime)s %(funcName)s %(lineno)-3d %(message)s',
# 级别颜色字典
level_styles=dict(
# debug 颜色:白色
debug=dict(color='white'),
# info 颜色:蓝色
info=dict(color='blue'),
# warning 颜色:黄色 且 高亮
warning=dict(color='yellow', bright=True),
# error 颜色:红色 且 高亮 且 加粗
error=dict(color='red', bold=True, bright=True),
# critical 颜色:灰色 且 高亮 且 背景色为红色
critical=dict(color='black', bold=True, background='red'),
),
# 这段代码定义了一个名为field_styles的字典 , 其中包含四个键值对。
# 每个键代表日志记录中的不同字段,而每个值是一个字典,它指定了与该字段相关联的样式选项。
# 具体来说,这些字段和样式选项如下:
# name:指定记录器的名称,将使用白色颜色。
# asctime:指定日志记录的时间戳,将使用白色颜色。
# funcName:指定记录消息的函数名称,将使用白色颜色。
# lineno:指定记录消息的源代码行号,将使用白色颜色。
field_styles=dict(
name=dict(color='white'),
asctime=dict(color='white'),
funcName=dict(color='white'),
lineno=dict(color='white'),
)
)
## 配置 StreamHandler:终端打印界面
# 这行代码定义了一个名为ch的日志处理器。
# 具体来说,它是logging.StreamHandler类的一个实例,用于将日志输出到标准输出流(即控制台)中。
# 在创建StreamHandler对象时,需要指定要使用的输出流
# 因此stream=sys.stdout参数指定了该对象将把日志写入到标准输出流中.
ch = logging.StreamHandler(stream=sys.stdout)
# 这段代码是 Python 中用于设置日志输出格式的语句。
# 它使用了一个名为 coloredFormatter 的格式化器对象,并将其传递给 ch.setFormatter() 方法来指定输出日志的样式。
# 具体来说,ch 是一个 Logger 对象,它代表了整个日志系统中的一个记录器。
# 可以通过该对象来控制日志的级别、输出位置等行为。而 setFormatter() 方法则用于设置该 Logger 输出日志的格式化方式
# 这里传递的是 coloredFormatter 格式化器对象。
# 在实际应用中,coloredFormatter 可以是自定义的 Formatter 类或者已经存在的 Formatter 对象。
# 这里 将 coloredFormatter - 彩色输出日志信息的格式化器 传入进去。
ch.setFormatter(fmt=coloredFormatter)
# 这段代码是在Python中添加一个日志记录器(logger)的处理器(handler)。其中,hdlr参数是指定要添加到记录器(logger)中的处理器(handler)对象,ch是一个代表控制台输出的处理器对象。
# 这行代码的作用是将控制台输出的信息添加到日志记录器中。
logger.addHandler(hdlr=ch)
# 这段代码用于设置日志级别为DEBUG,也就是最低级别的日志记录。
# 意思是在程序运行时,只有DEBUG级别及以上的日志信息才会被记录并输出,而比DEBUG级别更低的日志信息则不会被记录或输出。
# DEBUG(调试)、INFO(信息)、WARNING(警告)、ERROR(错误)和CRITICAL(严重错误)。
logger.setLevel(level=logging.DEBUG)
# 返回日志生成对象
return logger
def get_logger(name='', ):
'''
:param name: 日志等级
:return:
'''
# 初始化日志处理器 - 使用配置字典初始化日志处理器(将自定义配置加载到日志处理器中)
logging.config.dictConfig(LOGGING_DIC)
# 实例化日志处理器对象 - 并赋予日志处理器等级
logger = logging.getLogger(name)
# 返回日志生成对象
return logger
if __name__ == "__main__":
# # 示例:
# # (1)初始化日志处理器 - 使用配置字典初始化日志处理器(将自定义配置加载到日志处理器中)
# logging.config.dictConfig(LOGGING_DIC)
# # (2)实例化日志处理器对象 - 并赋予日志处理器等级
# # # logger1 = logging.getLogger('') # 默认为 '' 即以默认配置进行实例化
# logger1 = logging.getLogger('')
# # (3)当日志发生时,打印的提示语
# logger1.debug('这是日志生成语句')
logger_nor = get_logger(name='user')
logger_nor.info(msg="this is a info message")
logger_col = set_logging_color()
logger_col.info(msg="this is a debug message")
Ⅵ hashlib模块
# 摘要算法 : 只能加密不能解密
# 加密算法 : 用方法加密 加密后的字符串可以解密
【1】摘要算法
# Python的hashlib提供了常见的摘要算法
# 如MD5
# SHA1等等。
# 摘要算法又称哈希算法、散列算法。
# 它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
# 摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest
# 目的是为了发现原始数据是否被人篡改过。
# 摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数
# 计算f(data)很容易,但通过digest反推data却非常困难。
# 而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
【2】基础
import hashlib
import json
def one():
# 给原始数据
data = 'my name is dream'
# 转成二进制数据
data = data.encode('utf-8')
# 创建一个md5对象
md5 = hashlib.md5()
# 把原始数据给 md5 对象加密
md5.update(data)
# 返回加密后的结果
# 一种是加密后的 16 进制的 32 长度的字符串
print(md5.hexdigest()) # c4ca4238a0b923820dcc509a6f75849b
# 一种是二进制数据
print(md5.digest())
# 把常见的这种字符 用md5加密 ---> 扔到数据库里面
# 数据库中查 又返回
return md5.hexdigest()
【3】加盐
- 如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。
- 此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。
- 正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要
- 由于常用口令的MD5值很容易被计算出来
- 所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5
- 这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”
import random
def get_verify_code(n):
code = ''
for i in range(n):
random_int = str(random.randint(0, 9)) # 0-9之间的整数
random_upper = chr(random.randint(65, 90)) # A-Z之间的字母
random_lower = chr(random.randint(97, 122)) # a-z之间的字母
temp = random.choice([random_int, random_upper, random_lower])
code += temp
return code
def two():
code = get_verify_code(6)
# 给原始数据
data = 'my name is dream'
# data = data + code
# data = code + data
# 转成二进制数据
data = data.encode('utf-8')
code = code.encode('utf-8')
# 创建一个md5对象
md5 = hashlib.md5()
# 把原始数据给 md5 对象加密
md5.update(code)
md5.update(data)
# 返回加密后的结果
# 一种是加密后的 16 进制的 32 长度的字符串
print(md5.hexdigest()) # c4ca4238a0b923820dcc509a6f75849b
# 一种是二进制数据
print(md5.digest())
# 把常见的这种字符 用md5加密 ---> 扔到数据库里面
# 数据库中查 又返回
return md5.hexdigest()
'''
one = one()
two = two()
print(one) # a9824cf2cad8240003dd8071a4b315d3
print(two)
# 78e3b0d87878746c81a6aee148139459
# c0cd81c3993a68867f1ebeeb7e0b2535
# df200c13893926f399290212fbf8dc26
# b44c1a5212b71ee2bde885dfd8e0484e
'''
【4】案例
def save_data(data):
with open('user_data.json', 'w') as fp:
json.dump(obj=data, fp=fp)
def read_data():
with open('user_data.json', 'r') as fp:
data = json.load(fp=fp)
return data
def get_username_password():
username = input("username :>>>> ").strip()
password = input("password :>>>> ").strip()
return username, password
def encrypt_password(password, salt):
data = password + salt
data = data.encode()
md5 = hashlib.md5()
md5.update(data)
return md5.hexdigest()
def register():
username, password = get_username_password()
print(password)
salt = get_verify_code(6)
password = encrypt_password(password, salt)
save_data({'username': username, "password": password,'salt':salt})
def login():
username, password = get_username_password()
user_data_dict = read_data()
print(password)
salt = user_data_dict['salt']
password = encrypt_password(password, salt)
if username == user_data_dict['username'] and password == user_data_dict['password']:
print(f"登录成功!")
else:
print("登录失败")
register()
login()
标签:hashlib,logging,file,模块,time,print,path,日志,os
From: https://www.cnblogs.com/zyb123/p/18149321