python常用模块

re模块

在python要想使用正则必须借助于模块,re就是其中之一

''' 基本操作方法 '''
import re
re.findall('正则表达式', '带匹配的文本')   # 根据正则匹配除所有符合条件的数据
res = re.findall('a', 'eva chick jason')
print(res)		# ['a', 'a']    结果是一个列表(要么有元素,要么空列表)

在这里插入图片描述

res = re.search('正则表达式', '带匹配的文本')     # 根据正则匹配到一个符合条件的就结束
res = re.search('a', 'eva chick jason')
print(res)      # 结果对象  <_sre.SRE_Match object; span=(2, 3), match='a'>
print(res.group())  # 正在的结果 a

""" 如果没有符合条件的数据 那么search返回None 并且使用group会直接报错"""

使用group不报错解决方案:
    if res:
        print(res.group())
    else:
        print('不好意思,没有找到')

在这里插入图片描述

res = re.match('a', 'abcda')    # 根据正则从头开始匹配(文本内容必须子啊开头匹配上)
print(res)      # <_sre.SRE_Match object; span=(0, 1), match='a'>
print(res.group())  # a
""" 如果没有符合条件的数据,那么match返回None,而且使用group会直接报错"""

使用group不报错解决方案:
if res:
    print(res.group())
else:
    print('不好意思,没有找到')

在这里插入图片描述

re模块其他方法

import re
# 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
res = re.split('[ab]', 'abcd')
print(res)

在这里插入图片描述

# 类似于字符串类型的replace方法
res = re.sub('\d', 'H', 'eva3chick4yuan4', 1)   # 替换正则匹配到的内容
print(res)  # evaHchick4yuan4
res1 = re.sub('\d', 'H', 'eva3chick4yuan4')  # 不写默认替换所有
print(res1) # evaHchickHyuanH

在这里插入图片描述

# 返回元组,并提示替换了几处
res = re.subn('\d', 'H', 'eva3chick4yuan4', 1)
print(res)  # ('evaHchick4yuan4', 1)
res = re.subn('\d', 'H', 'eva3chick4yuan4')
print(res)  # ('evaHchickHyuanH', 3)

在这里插入图片描述

# 常用
regexp_obj = re.compile('\d+')
res = regexp_obj.search('absd213j1hjj213jk')
res1 = regexp_obj.match('absd213j1hjj213')
res2 = regexp_obj.findall('1213k1j2jhj21j3123hh')
print(res, res1, res2)

在这里插入图片描述

# 常用
res = re.finditer('\d+', 'ashdklah21h23kj12jk3klj112312121kl131')
print([i.group() for i in res])

在这里插入图片描述

res = re.search("1(\d{14})(\d{2}[0-9x])?$", ‘110105199812067023’)
print(res) # <_sre.SRE_Match object; span=(0, 18), match=‘110105199812067023’>
print(res.group()) # 110105199812067023
print(res.group(1)) # 10105199812067
print(res.group(2)) # 023
在这里插入图片描述

# findall针对分组优先展示   无名分组
res = re.findall("^[1-9]\d{14}(\d{2}[0-9x])?$", '110105199812067023')
print(res)      # ['023']
# 取消分组优先展示      无名分组
res1 = re.findall("^[1-9](?:\d{14})(?:\d{2}[0-9x])?$", '110105199812067023')
print(res1)     # ['110105199812067023']

在这里插入图片描述

# 有名分组
res = re.search('^[1-9](?P<xx>\d{14})(?P<zz>\d{2}[0-9x])?$','110105199812067023')
print(res)
print(res.group())
print(res.group(1))
print(res.group('xx'))
print(res.group('zz'))

在这里插入图片描述

正则实战案例

import re

# 读取带匹配的数据
with open(r'a.txt', 'r', encoding='utf8') as f:
    data = f.read()
# 利用正则匹配数据
# 分公司名称
title_list = re.findall('<h2>(.*?)</h2>', data)
# print(title_list)
# 分公司地址
address_list = re.findall("<p class='mapIco'>(.*?)</p>", data)
# print(address_list)
# 分公司邮箱
email_list = re.findall("<p class='mailIco'>(.*?)</p>", data)
# print(email_list)
# 分公司电话
phone_list = re.findall("<p class='telIco'>(.*?)</p>", data)

res = zip(title_list, address_list, email_list, phone_list)
for data_tuple in res:
    print("""
    公司名称:%s
    公司地址:%s
    公司邮箱:%s
    公司电话:%s
    """ % (data_tuple[0], data_tuple[1], data_tuple[2], data_tuple[3]))

collections模块

1.namedtuple(具名元组)
    from collections import namedtuple

    """
    namedtuple('名称',[名字1,名字2,...])
    namedtuple('名称','名字1 名字2 ...')
    """
    # point = namedtuple('坐标', ['x', 'y'])
    # res = point(11, 22)
    # print(res)  # 坐标(x=11, y=22)
    # print(res.x)  # 11
    # print(res.y)  # 22
    # point = namedtuple('坐标', 'x y z')
    # res = point(11, 22, 33)
    # print(res)  # 坐标(x=11, y=22, z=33)
    # print(res.x)  # 11
    # print(res.y)  # 22
    # print(res.z)  # 33
    # card = namedtuple('扑克', '花色 点数')
    # card1 = card('♠', 'A')
    # card2 = card('♥', 'K')
    # print(card1)
    # print(card1.花色)
    # print(card1.点数)

2.队列
    # 队列模块
    import queue  # 内置队列模块:FIFO
    # 初始化队列
    # q = queue.Queue()
    # 往队列中添加元素
    # q.put('first')
    # q.put('second')
    # q.put('third')
    # 从队列中获取元素
    # print(q.get())
    # print(q.get())
    # print(q.get())
    # print(q.get())  # 值去没了就会原地等待

3.双端队列
    from collections import deque
    q = deque([11,22,33])
    q.append(44)  # 从右边添加
    q.appendleft(55)  # 从左边添加
    print(q.pop())  # 从右边取值
    print(q.popleft())  # 从做边取值

4.有序字典
    normal_dict = dict([('name', 'jason'), ('pwd', 123), ('hobby', 'study')])
    print(normal_dict)
    {'hobby': 'study', 'pwd': 123, 'name': 'jason'}
    from collections import OrderedDict
    order_dict = OrderedDict([('name', 'jason'), ('pwd', 123), ('hobby', 'study')])
    print(order_dict)
    OrderedDict([('name', 'jason'), ('pwd', 123), ('hobby', 'study')])
    order_dict['xxx'] = 111
    order_dict
    OrderedDict([('name', 'jason'), ('pwd', 123), ('hobby', 'study'), ('xxx', 111)])
    normal_dict['yyy'] = 222
    normal_dict
    {'hobby': 'study', 'pwd': 123, 'yyy': 222, 'name': 'jason'}
    
5.默认值字典
	from collections import defaultdict
    values = [11, 22, 33,44,55,66,77,88,99,90]
    my_dict = defaultdict(list)
    for value in  values:
        if value>60:
            my_dict['k1'].append(value)
        else:
            my_dict['k2'].append(value)
    print(my_dict)

6.计数器
	res = 'abcdeabcdabcaba'
    # 统计字符串中每个元素出现的次数
    # new_dict = {}
    # for i in res:
    #     if i not in new_dict:
    #         new_dict[i] = 1
    #     else:
    #         new_dict[i] += 1
    # print(new_dict)
    from collections import Counter  # 计数器
    ret = Counter(res)
    print(ret)

time模块

"""
时间三种表现形式
	1.时间戳(秒数)
	2.结构化时间(一般是给机器看的)
	3.格式化时间(一般是给人看的)
	三种时间是可以相互转换的!!!
"""
1.time.sleep()  # 原地阻塞指定的秒数
2.time.time()  # 获取时间戳时间(自1970-1-1 00:00)

import time


# 获取当前格式化的时间字符串
 print(time.strftime('%Y-%m-%d'))  # 2021-11-25
 print(time.strftime('%Y-%m-%d %H:%M:%S'))  # 2021-11-25 11:48:34
 print(time.strftime('%Y-%m-%d %X'))  # 2021-11-25 11:48:34
 
"""
更多时间相关符号 保存到容易查找的位置即可
"""
本地时区的struct_time(结构化的时间)
# print(time.localtime())
UTC时区的struct_time(结构化时间)
# time.struct_time(
# tm_year=2021,
# tm_mon=11,
# tm_mday=25,
# tm_hour=11,
# tm_min=51,
# tm_sec=25,
# tm_wday=3,
# tm_yday=329,
# tm_isdst=0)


# print(time.time())
print(time.gmtime(11111111111))
# print(time.localtime())

在这里插入图片描述

datetime模块

import datetime
# print(datetime.date.today())  # 2021-11-25
# print(datetime.datetime.today())  # 2021-11-25 12:15:11.969769
"""date年月日  datetime年月日时分秒  time时分秒(MySQL django后期可以)"""
# res = datetime.datetime.today()
# print(res.year)  # 2021
# print(res.month)  # 11
# print(res.day)  # 25
# print(res.weekday())  # 获取星期(weekday星期是0-6) 0表示周一
# print(res.isoweekday())  # 获取星期(weekday星期是1-7) 1表示周一

"""时间差(timedelta)"""
# ctime = datetime.datetime.today()
# time_tel = datetime.timedelta(days=3)
# print(ctime)  # 2021-11-25 12:20:48.570489
# print(ctime - time_tel)  # 2021-11-22 12:21:06.712396
# print(ctime + time_tel)  # 2021-11-28 12:21:06.712396
"""
日期对象 = 日期对象 +/- timedelta对象
timedelta对象 = 日期对象 +/- 日期对象
"""
# ret = ctime + time_tel
# print(ret - ctime)  # 3 days, 0:00:00
# print(ctime - ret)  # -3 days, 0:00:00


# 小练习 计算举例今年过生日还有多少天
# birthday = datetime.date(2000, 11, 11)
# now_date = datetime.date.today()
# days = birthday - now_date
# print('距离生日还有{}天'.format(days))

# UTC时间与我们的东八区时间差 八个小时
# print(datetime.datetime.now())  # 2021-11-25 12:25:33.579310
# print(datetime.datetime.utcnow())  # 2021-11-25 04:25:33.579310

random随机数模块

import random

print(random.random())  # 随机产生一个0-1之间的小数
print(random.randint(1, 6))  # 随机产生一个1-6之间的整数   比如:掷骰子
print(random.uniform(1, 6))  # 随机产生一个1-6之间的小数
print(random.choice(['特等奖', '一等奖', '二等奖', '谢谢惠顾']))  # 随机抽取一个
print(random.sample(['安徽省', '江苏省', '海南省', '山东省'], 2))   # 随机抽取指定样本量

l = [2, 3, 4, 5, 6, 7, 8, 9, 'J', 'Q', 'K', 'A']
random.shuffle(l)   # 随机打乱容器类型中的诸多元素
print(l)
笔试题
# 随机验证码可以是由 数字 小写字母 大小写字母 任意组合
# 编写能够产生五位数的随机验证码
要求:五位,每位都可以是三种情况之一

def get_code(n):
# 提前定义一个存储验证码的变量
    code = ''
    # 由于需要产生五位,每一个操作都是一样的,所以肯定需要使用循环
    for i in range(n):
        # 随机产生一个数字
        random_int = str(random.randint(0, 9))
        # 随机产生一个大写字母
        random_upper = chr(random.randint(65, 90))
        # 随机产生一个小写字母
        random_lower = chr(random.randint(97, 122))
        # 随机选取一个
        temp = random.choice([random_int, random_upper, random_lower])
        # 拼接到字符串中
        code += temp
	return code
code1 = get_code(5)
code2 = get_code(10)
code3 = get_code(8)
print(code1, code2, code3)

在这里插入图片描述

os模块

是与操作系统打交道

import os
# 1. 创建单级目录(文件夹)
os.mkdir('dirname')
os.mkdir(r'dirname\作品')      # 报错

在这里插入图片描述

# 2. 创建多级目录(文件夹)
os.makedirs(r'dirname1\dirname2')

# 3. 删除空目录(文件夹)
os.rmdir(r'dirname')
os.removedirs(r'dirname')
	
# 4. 获取当前文件所在的路径(可以嵌套	则为上一层路径)
BASE_DIR = os.path.dirname(__file__)

# 5. 路径拼接能够自动识别不同操作系统分隔符问题
movie_dir = os.path.join(BASE_DIR, '作品')

# 6. 列举出指定路径下的文件名称(任意类型文件)
data_list = os.listdir('D:\dirname\作品')
while True:
    for i,j in enumerate(data_list):
        print(i + 1, j)
    choice = input('请选择想要的文件编号:').strip()
    if choice.isdigit():
        choice = int(choice)
        if choice in range(len(data_list) + 1):
            # 获取编号对应的文件名称
            file_name = data_list[choice - 1]
            # 拼接文件的完整路径   /专门用于路径拼接,而且能够自动识别当前操作系统的路径分隔符
            file_name = os.path.join(movie_dir, file_name)
            # 利用文件操作读写文件
            with open(file_path, 'r', encoding='utf8') as f:
                print(f.read())

# 7. 删除一个文件
os.remove('a.txt')

# 8. 修改文件名称
os.rename('老文件名', '新文件名')

# 9. 获取当前工作路径
print(os.getcwd())

# 10. 切换路径
os.chdir('D:/')
with open(r'a.txt', 'wb') as f:
    pass

# 11. 判断当前路径是否存在,如果存在,返回True;如果不存在,返回False
print(os.path.exists('a.txt'))  # False
print(os.path.exists('path'))   # True

# 12. 判断当前路径是否是文件,如果path是一个存在的文件,返回True。否则返回False
os.path.isfile(path)

# 13. 判断当前路径是否是文件夹,如果path是一个存在的目录,则返回True。否则返回False
os.path.isdir(path)

# 14. 获取文件大小(字节数)
os.path.getsize(path)

sys模块

主要与python解释器打交道

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version        获取Python解释程序的版本信息
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
异常处理和status
try:
username = sys.argv[1]
password = sys.argv[2]
if username == 'chick' and password == '123':
    print('正常执行文件内容')
else:
    print('用户名或密码错误')
except Exception:
    print('请输入用户名和密码')

序列化模块

json格式数据:跨语言传输

什么叫序列化——将原本的字典、列表等内容转换成一个字符串的过程叫序列化

序列化的目的

  1. 以某种存储形式使自定义对象持久化;
  2. 将对象从一个地方传递到另一个地方
  3. 使程序更具维护性
    在这里插入图片描述
import json

d = {'username': 'jason', 'pwd': 123}
# 1.将python其他数据转换成json格式字符串(序列化)
# import json
# res = json.dumps(d)
# print(res,type(res))  # {"username": "jason", "pwd": 123}
# 2.将json格式字符串转成当前语言对应的某个数据类型(反序列化)
# res1 = json.loads(res)
# print(res1,type(res1))  # {'username': 'jason', 'pwd': 123} <class 'dict'>
# bytes_data = b'{"username": "jason", "pwd": 123}'
# bytes_str = bytes_data.decode('utf8')
# bytes_dict = json.loads(bytes_str)
# print(bytes_dict,type(bytes_dict))
"""
暂且可以简单的理解为
    序列化就是将其他数据类型转换成字符串过程
        json.dumps()
    反序列化就是将字符串转换成其他数据类型
        json.loads()
"""
# 将字典d写入文件
# with open(r'a.txt','w',encoding='utf8') as f:
#     f.write(str(d))
# 将字典d取出来
# with open(r'a.txt','r',encoding='utf8') as f:
#     data = f.read()
# print(dict(data))

# 将字典d写入文件
# with open(r'a.txt','w',encoding='utf8') as f:
#     res = json.dumps(d)  # 序列化成json格式字符串
#     f.write(res)
# 将字典d取出来
# with open(r'a.txt','r',encoding='utf8') as f:
#     data = f.read()
# res1 = json.loads(data)
# print(res1,type(res1))

# d1 = {'username': 'tony', 'pwd': 123,'hobby':[11,22,33]}
# with open(r'a.txt', 'w', encoding='utf8') as f:
#     json.dump(d1, f)
# with open(r'a.txt','r',encoding='utf8') as f:
#     res = json.load(f)
# print(res,type(res))

d1 = {'username': 'tony好帅哦 我好喜欢', 'pwd': 123,'hobby':[11,22,33]}
print(json.dumps(d1,ensure_ascii=False))

"""
# 并不是所有的数据类型都支持序列化
json.JSONEncoder  查看支持的数据类型
"""

subprocess模块

import subprocess

"""
1.可以基于网络连接上一台计算机(socket模块)
2.让连接上的计算机执行我们需要执行的命令
3.将命令的结果返回
"""
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'))  # 获取错误命令执行之后的结果
"""
windows电脑内部编码默认为GBK
"""

hashlib模块

加密:将明文数据通过一系列算法变成密文数据(目的就是为了数据的安全)

加密算法:md系列 sha系列 base系列 hmac系列

 # 基本使用
import hashlib


# 1.先确定算法类型(md5普遍使用)
md5 = hashlib.md5()
# 2.将明文数据传递给md5算法(update只能接受bytes类型数据)
# md5.update('123'.encode('utf8'))
md5.update(b'123')
# 3.获取加密之后的密文数据(没有规则的一串随机字符串)
res = md5.hexdigest()
print(res)

在这里插入图片描述

1.加密之后的密文数据是没有办法反解密成明文数据的
市面上的破解 其实就是提前算出一系列明文对应的密文之后对比密文再获取明文

明文数据很大,可以分块多次调用update(),最后计算的结果是一样的:

import hashlib
# 1.先确定算法类型(md5普遍使用)
md5 = hashlib.md5()
# 2.将明文数据传递给md5算法(update只能接受bytes类型数据)
# md5.update('123'.encode('utf8'))
# md5.update(b'hellojason123')
md5.update(b'hello')
md5.update(b'jason')
md5.update(b'123')  # 4bd388611b31c548eedef14b16c9868c
# 3.获取加密之后的密文数据(没有规则的一串随机字符串)
res = md5.hexdigest()
print(res)  # 4bd388611b31c548eedef14b16c9868c

在这里插入图片描述

密文数据越长表示内部对应的算法越复杂 越难被正向破解

import hashlib
# 1.先确定算法类型(md5普遍使用)
md5 = hashlib.sha256()
# 2.将明文数据传递给md5算法(update只能接受bytes类型数据)
# md5.update('123'.encode('utf8'))
# md5.update(b'hellojason123')
md5.update(b'hello')
md5.update(b'jason')
md5.update(b'123')  # 6ec0f865ec4e9bcf9abc7f6c0e7268acfb2ba36f3e460fd592a214f7eacc92b0
# 3.获取加密之后的密文数据(没有规则的一串随机字符串)
res = md5.hexdigest()
print(res)  # 6ec0f865ec4e9bcf9abc7f6c0e7268acfb2ba36f3e460fd592a214f7eacc92b0

在这里插入图片描述

密文越长表示算法越复杂,对应的破解算法的难度越高
但是越复杂的算法所需要消耗的资源也就越多,密文越长基于网络发送需要占据的数据也就越大
具体使用什么算法取决于项目的要求,一般情况下md5足够了

涉及到用户密码存储,其实就是密文,只要用户自己知道明文是什么

  1. 内部程序员无法得知明文数据
  2. 数据泄露也无法得知明文数据

加盐处理

“”"
在对明文数据做加密处理过程前添加一些干扰项
“”"

import hashlib
# 1.先确定算法类型(md5普遍使用)
md5 = hashlib.md5()
# 2.将明文数据传递给md5算法(update只能接受bytes类型数据)
# md5.update('123'.encode('utf8'))
# 加盐(干扰项)
md5.update('公司内部自己定义的盐'.encode('utf8'))
# 真实数据
md5.update(b'hellojason123')
# 3.获取加密之后的密文数据(没有规则的一串随机字符串)
res = md5.hexdigest()
print(res)  # 4326fe1839d7c4186900eb2b356d4f8a

在这里插入图片描述
动态加盐

“”"
在对明文数据做加密处理过程前添加一些变化的干扰项
“”"

import hashlib
# 1.先确定算法类型(md5普遍使用)
md5 = hashlib.md5()
# 2.将明文数据传递给md5算法(update只能接受bytes类型数据)
# md5.update('123'.encode('utf8'))
# 加盐(干扰项)
# md5.update('公司内部自己定义的盐'.encode('utf8'))
# 动态加盐(干扰项)  当前时间 用户名的部分 uuid(随机字符串(永远不会重复))
import time
res1 = str(time.time())
md5.update(res1.encode('utf8'))
# 真实数据
md5.update(b'hellojason123')
# 3.获取加密之后的密文数据(没有规则的一串随机字符串)
res = md5.hexdigest()
print(res)  # 51033f8091108d2e399843e23b0b6a25

“”"
在IT互联网领域,没有绝对的安全可言,只有更安全
原因在于互联网的本质,就是通过网络(网卡)连接计算机
“”"
在这里插入图片描述

校验文件一致性

“”"
文件不是很大的情况下 可以将所有文件内部全部加密处理
但是如果文件特别大 全部加密处理相当的耗时好资源 如何解决???
针对大文件可以使用切片读取的方式
“”"

import hashlib
md5 = hashlib.md5()
with open(r'a.txt','rb') as f:
    for line in f:
        md5.update(line)
real_data = md5.hexdigest()
print(real_data)  # 29d8ea41c610ee5d1e76dd0a42c7e60a

with open(r'a.txt','rb') as f:
    for line in f:
        md5.update(line)
error_data = md5.hexdigest()
print(error_data)  # 738a56b49f24884ba758d1e4ab6ceb74
import os
# 读取文件总大小
res = os.path.getsize(r'a.txt')
# 指定分片读取策略(读几段 每段几个字节)  10   f.seek()
read_method = [0,res//4,res//2,res]

在这里插入图片描述

logging日志模块

import logging

# 日志有五个等级(从上往下重要程度不一样)
logging.debug('调试debug')  # 10
logging.info('消息info')  # 20
logging.warning('警告warn')  # 30
logging.error('错误error')  # 40
logging.critical('严重critical')  # 50
'''默认记录的级别在30及以上'''

# 简单使用
import logging
file_handler = logging.FileHandler(filename='x1.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('日志模块很好学 不要自己吓自己')
"""
1.如何控制日志输入的位置
    想在文件和终端中同时打印
2.不同位置如何做到不同的日志格式
    文件详细一些 终端简单一些
"""

日志模块详细介绍

import logging


# 1.logger对象:负责产生日志
logger = logging.getLogger('转账记录')
# 2.filter对象:负责过滤日志(直接忽略)
# 3.handler对象:负责日志产生的位置
hd1 = logging.FileHandler('a1.log',encoding='utf8')  # 产生到文件的
hd2 = logging.FileHandler('a2.log',encoding='utf8')  # 产生到文件的
hd3 = 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(hd1)
logger.addHandler(hd2)
logger.addHandler(hd3)
# 6.绑定formatter对象
hd1.setFormatter(fm1)
hd2.setFormatter(fm2)
hd3.setFormatter(fm1)
# 7.设置日志等级
logger.setLevel(30)
# 8.记录日志
logger.debug('写了半天 好累啊')

配置字典

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 = 'a3.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所在的路径添加环境变量'''
下载第三方模块的方式
	方式1:命令行借助于pip工具
        pip3 install 模块名 				# 不知道版本默认是最新版
        pip3 install 模块名==版本号 	 	# 指定版本下载
    	pip3 install 模块名 -i 仓库地址  	# 临时切换
        '''命令行形式永久修改需要修改python解释器源文件'''
    方式2:pycharm快捷方式
        settings 
        	project 
            	project interprter
                	双击或者加号
        点击右下方manage管理添加源地址即可
# 下载完第三方模块之后 还是使用import或from import句式导入使用
"""
pip命令默认下载的渠道是国外的python官网(有时候会非常的慢)
我们可以切换下载的源(仓库)
	(1)阿里云 http://mirrors.aliyun.com/pypi/simple/
    (2)豆瓣 http://pypi.douban.com/simple/
    (3)清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
    (4)中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
    (5)华中科技大学http://pypi.hustunique.com/
  
pip3 install openpyxl -i http://mirrors.aliyun.com/pypi/simple/
"""


"""
下载第三方模块可能报错的情况及解决措施
	1.报错的提示信息中含有关键字timeout
		原因:网络不稳定
		措施:再次尝试 或者切换更加稳定的网络
	2.找不到pip命令
		环境变量问题
	3.没有任何的关键字 不同的模块报不同的错
		原因:模块需要特定的计算机环境
		措施:拷贝报错信息 打开浏览器 百度搜索即可
			pip下载某个模块报错错误信息
"""

包介绍

  1. 什么是包?

     # 官网解释
     	包是一种通过使用‘ .模块名’来组织python模块名称空间的方式
     # 具体的:包就是一个包含有__init__.py文件的文件夹,所以其实我们创建包的目的就是为了用文件夹将文件/模块组织起来
     # 需要强调的是:
     	1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,报下一定要有该文件,否则import 包报错
     	2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块
    
  2. 为何要使用包

     包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起来
     随着功能越写越多,我们无法将所有功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,
     我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性
    
  3. 注意事项

     #1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
    
     #2、import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
     
     #3、包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间
    

  1. 1-9 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值