【周报】模块2

目录

上周回顾

常见内置函数

函数名 作用 参数
abs 求绝对值 (int | float)
all 判断容器类型中的数据是否都为True (容器类型)
any 判断容器类型中的数据是否存在True (容器类型)
bin 十进制转二进制 十进制数
oct 十进制转八进制 十进制数
hex 十进制转十六进制 十进制数
int 其他进制转十进制 其他进制数
bytes 对字符串类型数据进行编码 (str, 编码方式)
callable 判断变量名是否可调用 (名字)
chr 基于ASCII码 将数字转字符 (int)
ord 基于ASCII码 将字符转数字 (单个str)
dir 获取对象中可以用句点符取出的数据和方式 (名字)
divmod 获取除法运算后的整数与余数 常用作分页 (int, int)
enumerate 枚举容器类型中的数据值 (容器类型, start=int)
eval 识别字符串中的较简易的python代码 (str)
exec 识别字符串中的较复杂的python代码 (str)
hash 返回一串随机的数字(哈希值) \
help 查看帮助信息 \
isinstance 判断某个数据是否属于某个数据类型 (数据, 数据类型)
pow 幂指函数 (int, int)
round 四舍五入 有偏差 (int | float)

迭代

如何理解迭代

迭代,既更新换代,每次迭代都基于上一次的结果

可迭代对象

如何判断可迭代对象

可迭代对象可以使用句点符调用__iter__方法,并转化为迭代器对象

l1 = [1, 2, 3, 4, 5, 6, 7]
print(l1)  # [1, 2, 3, 4, 5, 6, 7]
print(l1.__iter__())  # <list_iterator object at 0x0000020E538F9040>

已知的可迭代对象有:

字符串 列表 字典 元组 集合 文件

不可迭代对象有:

整型 浮点型 布尔值 函数名

迭代器对象

迭代器对象的作用

迭代器对象给我们提供了一种不依赖于索引值的取值方式
正是有迭代器对象的存在 我们才可以从字典、集合这些无序排序的容器类型中获取数据

如何判断迭代器对象

迭代器对象可以通过句点符调用__iter__和__next__方法,迭代器对象无论调用多少次__iter__都还是他本身

l1 = [1, 2, 3, 4, 5]
iter_obj = l1.__iter__()
print(iter_obj)  # <list_iterator object at 0x000001CB9F4D90D0>
print(iter_obj.__next__())  # 1
print(iter_obj.__next__())  # 2
print(iter_obj.__next__())  # 3
print(iter_obj.__iter__())  # <list_iterator object at 0x000001CB9F4D90D0>

可迭代对象和迭代器对象的关系

可迭代对象调用__iter__会产生一个迭代器对象
迭代器对象无论使用多少次__iter__都还是他本身

迭代器对象取值

l1 = [1, 2, 3, 4, 5]
# l1 并没有 __next__ 方法 因为它是可迭代对象
res = l1.__iter__()  # 可迭代对象使用__iter__将产生一个迭代器对象 并赋值给res
print(res.__next__())  # 1  使用__next__就可以取出下一个数据

# 不使用for循环 依次打印列表中所有数据
l1 = [1, 2, 3, 4, 5]
res = l1.__iter__()
n = 0
while n < len(l1):
    print(res.__next__())
    n += 1

# 运行结果
# 1
# 2
# 3
# 4
# 5

迭代取值与索引取值的区别

迭代取值能够对无序的数据集进行取值,但只能一个个获取数据,并且不能重复获取

索引取值能够随意重复获取任意位置的数据,但无法对无序的数据集进行取值

双下方法的另一种形式

res = l.__iter__()  # 可以简写 res = iter(l)
res.__next__()  # 可以简写 next(res)
# 不推荐

迭代器对象的特殊性

迭代器对象 通过打印操作无法直接看出内部的情况
这个时候能帮你节省空间
相当于一个工厂 需要数据时 一个个取出

异常捕获

如何理解异常

异常在程序运行中出现则会是程序直接结束
既程序员口中的BUG

异常的结构

image

关键字line

精准标记出异常的出现位置 一般来说看最后的超链接

最后一行冒号的左边

异常类型

最后一行冒号的右边

异常的具体原因(关键)

异常的分类

语法错误

不允许出现!出现就立马修改!

逻辑错误

允许出现 运行之后修改错误即可

什么时候需要异常

有不确定因素报错的情况下

异常捕获原理

预知了错误的可能 并提前给出相应的处理措施

异常语法结构

# 基本语法结构
try:
    可能出错的代码  # 被try监控
except 错误类型1 as e:  # e就是错误信息
    针对错误类型1的解决方案
except 错误类型2 as e:  # e就是错误信息
    针对错误类型2的解决方案
except 错误类型3 as e:  # e就是错误信息
    针对错误类型3的解决方案


# 万能结构  不推荐
# 1
try:
    可能出现错误的代码
except BaseException:
    解决方案

# 2
try:
    可能出现错误的代码
except Exception:
    解决方案

异常捕获其他操作补充

# else和finally
try:
    可能出现错误的代码
except 错误类型:
    针对错误类型的解决方法
else:
    不报错后执行的代码
finally:
    报不报错都会执行的代码
# assert 断言
name = 'jason'
assert isinstance(name, list)  # 断言name 属于 list类型 如果不对则报错 对则执行后面的代码 感觉和if作用差不多
print('哈哈哈哈哈')  # 显然name不是list类型 所以这步不会执行

image

# raise 主动抛出异常
name = 'jason'
if name == 'jason':
    raise Exception('鸡你太美')
else:
    raise Exception('你干嘛~')

image

生成器

生成器对象的本质

本质就是迭代器对象
但迭代器对象是编译器提供给我们的
而生成器对象是我们根据迭代器对象 依赖yield关键字 生成的

生成器对象的作用

优化代码 提供一种不依赖与索引的取值方式 并在需要数据时一个一个取出 节省了占用空间

代码实现

# yield关键字
def func():
    print(123)
    yield
func()  # 运行后发现 啥也没有
# 原来 当函数体内有yield关键字 第一次运行时并不会执行函数体代码 而是产生一个迭代器对象 既生成器 可以由一个变量名接收
res = func()
res.__next__()  # 123 通过调用__next__方法就可以调用yield上面的代码

# 当然 函数体内可以不止有一个yield
def func():
    print(1)
    yield
    print(2)
    yield
    print(3)
    yield
    print(4)
    yield

res = func()
res.__next__()  # 1
res.__next__()  # 2
res.__next__()  # 3
res.__next__()  # 4

# yield 后面可以添加返回值 和return用法相似
def func():
    print(1)
    yield 111
    print(2)
    yield 222
    print(3)
    yield 333

res = func()
res1 = res.__next__()  # 1
res2 = res.__next__()  # 2
res3 = res.__next__()  # 3
print(res1)  # 111
print(res2)  # 222
print(res3)  # 333

yield关键字其他用法

# yield可以在函数中充当一个参数
def func(name, s_name=None):
    print(f'{name}要来检查博客辣!!!')
    while True:
        s_name = yield
        print(f'哦吼!{s_name}博客没写 录音也没录')

res = func('jason')  # 同样第一次调用不会执行函数体代码
res.__next__()  # jason要来检查博客辣!!!  必须先调用一次__next__()
res.send('快男')  # 哦吼!快男博客没写 录音也没录  send()用于传值给yield 并自动调用__next__方法
res.send('XXX')  # 哦吼!XXX博客没写 录音也没录

生成器表达式

n = 1
l1 = (i + n for i in range(10))
print(l1)  # <generator object <genexpr> at 0x000001A04F4DCAC0>  "元组生成式"生成了一个生成器对象
# 只有在执行__next__时 i+1才会执行 并将结果返回
print(list(l1))  # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
l2 = (i + n for i in range(10))
n = 2  # 修改了n = 2
print(list(l2))  # [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 执行了修改后的n


# 面试题
def add(n, i):  # 普通函数 返回两个数的和  求和函数
    return n + i
def test():  # 生成器
    for i in range(4):
        yield i
g = test()  # 激活生成器
for n in [1, 10]:
    g = (add(n, i) for i in g)
    """
    第一次for循环
        g = (add(1, i) for i in g)  # 这里并没有调用 只是产生了一个迭代器(生成器)
    第二次for循环
        g = (add(10, i) for i in (add(10, i) for i in g))  # 这里的add()中的n变为了10 然后再产生了一个生成器
    """
res = list(g)  # 这里才进行了调用 n为10 所以全部生成器中n都为10
"""
大致过程
先:g = (add(10, i) for i in (10, 11, 12, 13))
再  res = (20, 21, 22, 23)
"""
print(res)

#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23]  # 正确答案
#D. res=[21,22,23,24]

模块

如何理解模块

模块就像一个工具箱 里面装有各种工具
导入了模块就能使用其中的名字和功能

模块的分类

内置模块

自定义模块

第三方模块

模块表现形式

py文件
含有多个py文件的文件夹

模块的两种导入方式

# 方式1:import ...
import time
time.sleep()

# 方式2: from ... import ...
from time import sleep
sleep()

# import ...
# 优点 通过模块.的方式可以使用到模块内的全部名字 且不会冲突
# 缺点 暴露太多 有时候并不想所有东西都可以通过模块.的方式获取
# from ... import ...
# 优点 指名道姓的使用指定的名字 并且不需要加模块名前缀
# 缺点 名字容易于当前全局名称空间的名字产生冲突

模块补充说明

# 起别名
# 在多个模块名字相同 或 模块名较复杂的情况下 可以通过 as 别名 的方式取一个别名
# 再通过别名.的形式调用模块内的功能
import UserInfoGetTargetName as UIGT
UIGT.XXXXX

from a import d as a_d
from b import d as b_d
from c import d as c_d

# 同时导入多个名字
# 建议同一目录下的模块  或 功能相似的模块 采用统一导入
from a import b, c, d
import run, runfast, runslowly

判断文件类型

所有py文件都含有一个内置的名字__name__
当py文件为执行文件时__name__为__main__
当py文件为被导入文件时__name__为文件名(模块名)

循环导入问题

# 以下为a.py的内容
import b
name = 'from a'
print(b.name)

# 以下为b.py的内容
import a
name = 'from b'
print(a.name)

# 无论执行哪个文件都会报错
# 解决措施
# 在导入前先把东西准备好
# 以下为a.py的内容
name = 'from a'
import b
print(b.name)

# 以下为b.py的内容
name = 'from b'
import a
print(a.name)

模块查找顺序

先在内存中查找>>>再去内置中查找>>>在去环境变量中查找(sys.path)
所有的路径都是参照执行文件来的
可以通过 sys.path.append() 的方式添加文件的绝对路径
可以通过 from ... import ... 获取相对路径下的模块 起始位置一定是执行文件所在的位置

绝对导入与相对导入

前提

只要提到模块的导入 那么sys.path永远以执行文件为基准

绝对导入

from ccc.ddd.eee impot a

image

绝对导入会按照当前执行文件的sys.path一层层的往下查找
pycharm默认将项目根目录存放在sys.path中 所以从项目根目录一层层导入绝对不会出错

image

但若不是用pycharm运行 则需要将项目根目录路径添加到sys.path
所以还是养成手动将根目录添加到sys.path中的习惯
提高项目兼容性

image

相对导入

模块文件之间的导入会使用到相对导入
但绝对导入更好

.在路径中的作用

标点 作用
. 当前文件路径
.. 上一级文件路径
../.. 上上级文件路径

相对导入可以不参考执行文件所在的路径 直接以当前模块路径为准
但相对导入有些缺陷:
1.只能在模块文件中使用 不在执行文件中使用
2.相对导入在项目比较复杂的情况下 可能会出错

建议:多用绝对导入 少用相对导入

包的概念

如何理解包

专业角度:内部含有__init__.py的文件夹
直观角度:内部有模块文件的文件夹
作用:存放多个模块 仅仅是更加方便的管理模块文件

包的使用

import 包名

image
可以看到这里导入的是包内的__init__.py文件
但也可以通过from ... import ...的方式跳过__init__.py文件直接获取包内的模块文件

不同版本导入包的差异

python3解释器中包内有没有__init__.py都无所谓了
而python2解释器中包内严格需求要有__init__.py

python2环境下

image

编程思想

小白阶段

按需求从上往下的编写代码(面条版)-----单文件

image

函数阶段

打破从上往下编写代码的空间限制 按功能将代码封装为不同函数-----单文件

image

模块阶段

把封装好的函数按功能分类并拆分到不同的模块中-----多文件

image
image

每个阶段都使代码变得更加规范

软件开发目录规范

目的

为了更加方便、高效、快捷的管理代码

文件夹 作用 内含文件
conf 存储程序的配置文件 settins.py
core 存储程序的核心功能 src.py
bin 存储程序的启动文件 start.py
lib 存储程序的公共功能 common.py
db 存储程序的数据文件 userinfo.txt
log 存储程序的日志文件 log.log
interface 存储程序的接口文件 user.py、good.py
readme(单个文件) 用于介绍程序的功能 \
requirements.txt(单个文件) 记录了项目所需的第三方模块名称和版本信息 \

collections模块

作用

给我们提供了更多的数据类型

名字 类型
namedtuple 具名元组
deque 双端队列
OrderedDict 有序字典
defaultdict 默认值字典
counter 计数器

time模块

作用

提供了很多时间的操作

函数 作用
time() 获取时间戳
localtime() 获取结构化时间
gmtime() 获取英国伦敦的结构化时间
strftime() 根据某舟格式来格式化时间
sleep() 程序在原地等待自定义的时间

时间的格式

在striftime()中输入特定的格式可以获取特定的时间字符串

import time

res = time.strftime('%Y-%m-%d %H:%M:%S')
print(res)  # 2022-07-15 17:11:02

res = time.strftime('%Y-%m-%d %X')
print(res)  # 2022-07-15 17:11:02
格式 作用
%Y 获取年份
%m 获取月份
%d 获取天份
%H 获取小时
%M 获取分钟
%S 获取秒数
%X 获取时分秒

datetime模块

与time模块类似 都是时间相关操作的模块

使用

import datetime

res = datetime.datetime.today()
print(res)  # 2022-07-15 17:18:49.814341
res1 = datetime.date.today()
print(res1)  # 2022-07-15
"""
date        年月日
datetime    年月日 时分秒
"""

print(res.year)  # 2022
print(res.month)  # 7
print(res.day)  # 15
print(res.hour)  # 17
print(res.minute)  # 22
print(res.second)  # 16
print(res.weekday())  # 4
print(res.isoweekday())  # 5
"""
year    年
moth    月
day     日
hour    时
minute  分
second  秒
weekday()   周几  周一为0
isoweekday()周几  周一为1
"""

# timedelta 日期延期/提前
res = datetime.date.today()
tl = datetime.timedelta(days=3)
print(res)  # 2022-07-15
print(res + tl)  # 2022-07-18
print(res - tl)  # 2022-07-12
"""
timedelta括号内有很多参数 没有的时间可以通过换算得来
"""

os模块

语句

# 导入
import os
import os
# 创建目录  mkdir()  makedirs()
os.mkdir(r'aaa')  # 创建单级文件 但不能创建多级文件 但mkdir该语句在很多系统都通用
os.makedirs(r'aaa\bbb\ccc')  # 创建多级文件 也可以创建单级文件
import os
# 删除目录  rmdir() removedirs()
os.rmdir(r'aaa')  # 删除单级文件 但文件内不能有数据 不能删除多级文件

os.removedirs(r'aaa\bbb\ccc')  # 可以删除多级文件 
# 但若文件内有数据则无法删除 从内到外依次删除空的文件夹 直到遇到有数据的文件夹
import os
# 列举指定文件下的文件名称 listdir()  结果返回的是列表
# aaa文件夹中有 a.py b.py c.py
res = os.listdir(r'aaa')
print(res)  # ['a.py', 'b.py', 'c.py']
import os
# 重命名文件 rename() 删除文件 remove()
os.rename('a.txt', r'aaa.txt')  # 将a.txt更改为aaa.txt
os.remove('aaa.txt')  # 删除aaa.txt
import os
# 获取当前工作路径  getcwd()  获取的是绝对路径
print(os.getcwd())  # F:\pythonProject\day24
os.chdir(r'..')  # chdir() 类似 控制台中的cd
print(os.getcwd())  # F:\pythonProject
import os
# 与程序启动文件相关
print(os.path.abspath(__file__))  # 获取当前文件的绝对路径(可以不记)
print(os.path.dirname(__file__))  # 获取当前文件所在的目录路径(必须得记)
import os
# 判断路径是否存在(文件、目录)  exists()  isdir()  isfile()
# exists() 就像 isdir() 和 isfile() 功能的结合版
# isdir() 只能判断路径是否是目录(既文件夹)
# isfile() 只能判断路径是否是文件
# exists() 可以判断路径是否存在
import os
# 拼接路径  join()
relative_path = 'a.txt'
absolute_path = r'D:\pythonProject\day24\ccc\ddd\eee'
res = os.path.join(absolute_path, relative_path)  # 两个路径之间会根据当前系统自动添加\或/(不同系统之间路径的分隔符不同)
print(res)  # D:\pythonProject\day24\ccc\ddd\eee\a.txt
import os
# 获取文件大小 getize()
# a.txt 的内容如下
# 你好aaaa
print(os.path.getsize(r'a.txt'))  # 10  计算的是字节量  1个中文3字节 1个英文1个字节 所以是10字节

sys模块

语句

import sys

print(sys.path)  # 结果是列表
print(sys.version)  # 查看解释器版本信息
print(sys.platform)  # 查看当前平台
res = sys.argv
"""需求 命令行执行当前文件必须提供用户名和密码 否则不准执行"""
if len(res) == 3:
    username = res[1]
    password = res[2]
    if username == 'jason' and password == '123':
        print('您可以正常执行该文件')
    else:
        print('用户名或密码错误')
else:
    print('请填写用户名和密码')
# 上述校验也可以使用异常捕获实现(课下实现)

res = sys.argv
try:
    username = res[1]
    password = res[2]
    if username == 'jason' and password == '123':
        print('您可以正常执行该文件')
    else:
        print('用户名或密码错误')
except IndexError:
    print('请输入用户名和密码')

json模块

语句

import json

res = json.dumps(d)  # 序列化 将其他数据类型转换成json格式字符串
print(res, type(res))  # {"name": "jason", "pwd": 123} <class 'str'>
res1 = json.loads(res)  # 反序列化 将json格式字符串转换成对应编程语言中的数据类型
print(res1, type(res1))  # {'name': 'jason', 'pwd': 123} <class 'dict'>


"""
dumps()     将其他数据类型转换为json格式字符串
loads()     将json格式字符串z换行成对应的数据类型

dump()      将其他数据类型直接以json格式字符串写入文件
load()      将文件中json格式字符串读取出来并转换成对应的数据类型
"""

本周回顾

正则表达式

前言:该知识点不属于任何一门编程语言 是一个独立的知识点

用纯python代码实现手机号验证

# 纯python
# 1.输入手机号
phone = input('请输入手机号>>>:').strip()
# 2.判断是否是纯数字
if phone.isdigit():
    # 3.判断是否以13 15 17 18 19开头
    if phone.startswith('13') or phone.startswith('15') or phone.startswith('17') or phone.startswith('18') or phone.startswith('19'):
        # 4.判断是否长度为11位
        if len(phone) == 11:
            print('合法辣')
        else:
            print('手机长度不对')
    else:
        print('开头不对')
else:
    print('请输入正确手机号')

使用正则实现手机号验证

# 正则
import re

# 1.输入手机号
phone = input('请输入手机号>>>:').strip()
# 2.使用match方法
if re.match('^(13|15|17|18|19)[0-9]{9}', phone):
    print('合法')
else:
    print('不合法')

正则表达式本质上就是使用一些符号的组合产生一些特殊的含义
然后去字符串中筛选出符合条件的数据

正则表达式之字符组

字符组在没有量词修饰下一次只会针对一个数据值

字符组 作用
[0-9] 每次匹配一个数字
[a-z] 每次匹配一个小写字母
[A-Z] 每次匹配一个大写字母
[0-9a-zA-Z] 每次匹配一个数字或大写字母或小写字母

中括号内编写的多个数据彼此之间为或关系

正则表达式之特殊符号

特殊符号在没有量词修饰的情况一个符号一次只会针对一个数据值

特殊符号 作用
. 匹配除换行符以外的所有字符
\w 匹配下划线、字母、数字
\W 匹配非(下划线、字母、数字)
\d 匹配数字
^ 匹配开头
$ 匹配结尾
a|b 匹配a或匹配b
() 给正则表达式分组 不影响正则表达式的匹配
[] 匹配字符组中的字符
[^] 匹配非字符组中字符的字符

正则表达式之量词

在正则表达式中所有的量词默认都是贪婪匹配(尽可能多的)
量词不能单独使用 必须跟在表达式的后面 并且只能影响紧挨着的左边那一个

量词 作用
* 匹配0个或多个
+ 匹配1个或多个
? 匹配0个或1个
匹配n个
匹配n到m个

贪婪匹配与非贪婪匹配

# 贪婪匹配
s = '<div>这是个测试文本</div>'
res = re.findall('<.*>', s)
print(res)  # ['<div>这是个测试文本</div>']

# 非贪婪匹配
s = '<div>这是个测试文本</div>'
res = re.findall('<.*>', s)
print(res)  # ['<div>', '</div>']

"""
所有的量词默认都是贪婪匹配 但是如果在量词的后面紧跟一个问号
那么就会变成非贪婪匹配
小技巧:以后我们在使用贪婪匹配或者非贪婪匹配的时候一般都是用.*或者.*?
并且结束的标志有上述符号左右两边添加的表达式决定
"""

取消转义

正则表达式中 \n
python中 r'\n'

re模块

re模块是python中处理正则的一种模块 并不是唯一

findall()

import re
# findall()  通过正则表达式筛选出文本中所有符合的数据 返回值为列表
res = re.findall('abc', 'abcabcabcabc')
print(res)  # ['abc', 'abc', 'abc', 'abc']

finditer()

# finditer() 通过正则表达式筛选出文本中所有符合的数据 返回值为迭代器对象
res = re.finditer('abc', 'abcabcabcabc')
print(res)  # <callable_iterator object at 0x000001BF27557220>
print(res.__next__())  # <re.Match object; span=(0, 3), match='abc'>
print(res.__next__().group())  # abc
# search()  通过正则表达式筛选文本中第一个符合条件的数据
res = re.search('abc', 'abcabcabcabc')
print(res)  # <re.Match object; span=(0, 3), match='abc'>
print(res.group())  # abc

match()

# match()  从头开始匹配正则表达式 若头部都不符合 则直接退出  类似^
res = re.match('abc', 'abcabcabcabc')
print(res)  # <re.Match object; span=(0, 3), match='abc'>
print(res.group())  # abc

res = re.match('abc', 'bcabcabcabc')
print(res)  # None

compile()

# compile()  提前准备好正则 方便使用 减少代码冗余
obj = re.compile('abc')
print(re.findall(obj, 'abcabc'))  # ['abc', 'abc']
print(re.findall(obj, 'abcabcabc'))  # ['abc', 'abc', 'abc']
print(re.findall(obj, 'abcabcccabcabc'))  # ['abc', 'abc', 'abc', 'abc']

findall() 补充

# findall针对分组的正则表达式匹配到的结果 优先展示
res = re.findall('a(b)c', 'abcabcabcabc')
print(res)  # ['b', 'b', 'b', 'b']
res = re.findall('a(bc)', 'abcabcabcabc')
print(res)  # ['bc', 'bc', 'bc', 'bc']

# 可以使用:?取消优先展示
res = re.findall('a(?:b)c', 'abcabcabcabc')
print(res)  # ['abc', 'abc', 'abc', 'abc']
res = re.findall('a(?:bc)', 'abcabcabcabc')
print(res)  # ['abc', 'abc', 'abc', 'abc']

还能起别名(?P<name>正则表达式)

import re
res = re.finditer('a(?P<cccc>b)c', 'abcabcabc')
print(res.__next__().group('cccc'))  # b

网络爬虫

什么是互联网

将计算机连接在一起的网络

互联网发明的目的

数据分享

上网的本质

访问他人计算机内的资源(一般有专门用来供他人访问的计算机 这种计算机称之为服务器)

网络爬虫的本质

模拟计算机浏览器想目标网站发送请求获取数据并筛选
只要是浏览器可以访问的数据 网络爬虫一般来说都可以

第三方模块的下载

方式1:pip install 模块名==版本号
方式2:pycharm内在settings里下载

下载速度慢

pip 工具默认使用国外的源
可以手动添加源
清华大学 :https://pypi.tuna.tsinghua.edu.cn/simple/
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科学技术大学 :http://pypi.mirrors.ustc.edu.cn/simple/
华中科技大学:http://pypi.hustunique.com/
豆瓣源:http://pypi.douban.com/simple/
腾讯源:http://mirrors.cloud.tencent.com/pypi/simple
华为镜像源:https://repo.huaweicloud.com/repository/pypi/simple/

pip3.8 install 模块名 -i 源地址

下载报错

1.pip工具版本过低 直接拷贝提示信息里面的更新命令即可
python38 -m pip install --upgrade pip
2.网络波动 关键字是Read timed out
只需要重新下载几次即可 或者切换一个网络稳定一点的
3.有些模块在下载使用之前需要提前配置指定的环境
结合具体情况 百度搜索

openpyxl模块

用于操作excel表格

python中操作excel表格的模块

1.openpyxl
属于近几年比较流行的模块
对03版excel之前的版本不太兼容
2.xlwt、xlrd
同样可以操作excel表
对03版以前的excel兼容性要好与openpyxl 但使用方式较复杂

excel版本的变更

03版之前 excel文件后缀为 .xls
03版之后 excel文件后缀为 .xlsx
如果是苹果本 excel文件后缀为 .csv

openpyxl模块实操

pip install openpyxl

# 创建文件
from openpyxl import Workbook  # 导入模块
wb = Wookbook()  # 创建excel文件对象

wb1 = wb.create_sheet('sheet1')  # 创建一个名为 sheet1 的工作簿
wb2 = wb.create_sheet('sheet2')  # 创建一个名为 sheet2 的工作簿

wb1.title = 'sheet111'  # 修改工作簿对象 wb1 的名字为 sheet111
wb.save(r'111.xlsx')  # 保存excel文件

wb1['A1'] = '这是excelA1的内容'  # 可以通过 ['位置'] 的方式在指定位置填写内容
wb1.append(['username', 'password', 'age', 'hobby'])  # 也可以通过.append直接添加一行多个数据
# 也可以写算数公示
# wb1['A3'] = '=sum(A1:A2)'

wb.save(r'111.xlsx')

image
image
image

openpyxl模块读取数据

# openpyxl读写数据使用的模块不一样
from openpyxl import Workbook, load_workbook

# wb = Workbook()
# wb1 = wb.create_sheet('红浪漫消费记录', 0)
# wb2 = wb.create_sheet('天上人间消费记录')
# wb3 = wb.create_sheet('白马会所消费记录')
#
#
# wb1.append(['username', 'gender', 'age'])
# wb1.append(['jason', 'male', 18])
# wb1.append(['kevin', 'female', 38])
# wb1.append(['tony', 'male', 58])
# wb1['C5'] = '=AVERAGE(C2:C4)'
#
# wb.save(r'111.xlsx')
wb = load_workbook(r'111.xlsx')
print(wb.sheetnames)  # ['红浪漫消费记录', 'Sheet', '天上人间消费记录', '白马会所消费记录']
wb1 = wb['红浪漫消费记录']
# print(wb1.max_row)
# print(wb1.max_column)
# print(wb1['A1'].value)
# print(wb1.cell(row=2, column=2).value)

for i in wb1.rows:
    print([j.value for j in i])

# ['红浪漫消费记录', 'Sheet', '天上人间消费记录', '白马会所消费记录']
# ['username', 'gender', 'age']
# ['jason', 'male', 18]
# ['kevin', 'female', 38]
# ['tony', 'male', 58]
# [None, None, '=AVERAGE(C2:C4)']

random随机数模块

import random
random.random()  # 返回一个0到1之间的随机小数
random.randint(1, 10)  # 返回一个1到10之间的整数 包括1和10
random.randrange(1, 10)  # 和randint相似 取得到1取不到10
random.choice(列表)  # 随机抽取一个
random.sample(列表, 个数)  # 自定义抽取个数
random.shuffle(列表)  # 打乱 洗牌

"""面试题:5位验证码 每位可以是大写字母、小写字母、数字"""
code = ''
for i in range(5):
    random_int = str(random.randint(0, 9))
    random_lower = chr(random.randint(97, 122))
    random_upper = chr(random.randint(65, 90))
    code += random.choice([random_int, random_lower, random_upper])

print(code)  # b36Eh

# 也可以封装 自定义个数

def get_code(n):
    code = ''
    for i in range(n):
        random_int = str(random.randint(0, 9))
        random_lower = chr(random.randint(97, 122))
        random_upper = chr(random.randint(65, 90))
        code += random.choice([random_int, random_lower, random_upper])
    return code

code = get_code(10)  # 0I2g9lX944

hashlib加密模块

什么是加密

将看得懂的文字(明文) 处理变成看不懂的文字(密文) 的过程

为什么要加密

为了数据的安全

如何判断数据是否加密

加密后的数据一般由无规则的字母、数字、符号组成

加密算法

就是加密所采用的策略 类似编码时按照指定的规范编码
不同加密算法结果不同 复杂度也不同
一般情况下 加密后的结果越长 加密越复杂

常见加密算法

md5 sha系列 hmac base64

import hashlib
md5 = hashlib.md5()  # 使用md5加密策略
md5.update(b'123')  # 添加明文 数据必须是bytes类型
res = md5.hexdigest()  # 获取加密之后的值
print(res)  # 202cb962ac59075b964b07152d234b70

# 一般情况下 会对明文进行加盐处理 这样可以使密文有干扰项 安全性有提高
# 加盐处理就是在明文前后添加指定或自己知道他人不容易知道的规范字符

subprocess模块

import subprocess

sub = subprocess.Popen('cccc',
                       shell=True,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE
                       )

# stdout执行命令之后正确的返回结果
print(sub.stdout.read().decode('gbk'))
# stderr执行命令报错之后的返回结果
print(sub.stderr.read().decode('gbk'))  # error

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 = '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配置
        # '购物车记录': {
        #     'handlers': ['default','console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
        #     'level': 'WARNING',
        #     'propagate': True,  # 向上(更高level的logger)传递
        # },  # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
    },
}

logging.config.dictConfig(LOGGING_DIC)  # 自动加载字典中的配置
# logger1 = logging.getLogger('购物车记录')
# logger1.warning('尊敬的VIP客户 晚上好 您又来啦')
# logger1 = logging.getLogger('注册记录')
# logger1.debug('jason注册成功')
logger1 = logging.getLogger('红浪漫顾客消费记录')
logger1.debug('慢男 猛男 骚男')

posted on   祁珏  阅读(91)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示