22、常见内置和第三方函数

一、time与datetime模块

  1. 时间分为3种格式
    1. 时间戳: 从1970到现在经过的秒数
      - 作用:用于时间间隔的计算
    2. 按照某种格式显示的时间: 例如:2021-01-01 11:11:11
      - 作用: 用于展示时间
    3. 结构化的时间
      - 作用: 主要用于获取当前时间的某一部分
import time
from datetime import datetime, timedelta

# - time
# 1. 获取时间戳:
print(time.time())

# 2. 按照某种格式显示的时间: 例如:2021-01-01 11:11:11, 作用:
print(time.strftime("%Y-%m-%d %H:%M:%S %p"))
print(time.strftime("%Y-%m-%d %X"))

# 3. 结构化的时间
res = time.localtime()
print("结构化的时间:", time.localtime())
print(res.tm_mday)
  1. datetime
# - datetime
# 第二种格式化的时间是最常用的时间形式, datetime擅长的
print(datetime.now())

# 时间的加减
res = datetime.now() + timedelta(weeks=+2, seconds=+120)
print("加后的时间:", res)
res = datetime.now() + timedelta(days=-3)
print("减后的时间:", res)

# 需要掌握的操作
# 一、时间格式的转换
# struck_time(结构化时间) -> 时间戳
s_time = time.localtime()
print(s_time)
print(time.mktime(s_time))

# 时间戳 -> struck_time
tp_time = time.time()
print(time.localtime(tp_time))
print(time.gmtime())  # 世界标准时间,差8个小时, 我们用的是北京时间,上海时区

# struck_time -> 结构化的字符串的时间
s_time = time.localtime()
print(time.strftime("%Y-%m-%d %H:%M:%S", s_time))

# 结构化的字符串的时间 -> struck_time
print("结构化的字符串的时间转化为struck_time:", time.strptime("2021-01-01 11:11:11", "%Y-%m-%d %H:%M:%S"))

# 真正常用的只有一点:结构化的字符串的时间 -> timestamp
# 需求 + 7
s_text = "2021-01-01 11:11:11"
res = datetime.strptime(s_text, "%Y-%m-%d %X") + timedelta(days=7)
print("结果:", str(res))
print(type(str(res)))

3 . 其他知识

# 其他知识
time.sleep(1)  # 爬虫重要
print(time.asctime())  # 通常用于linux
print(datetime.utcnow())  # 世界标准时间
print(datetime.fromtimestamp(time.time()))

时间格式间的转化

二、random模块

  1. 用来去随机值的
import random

print("大于0且小于1之间的小数: ", random.random())  # (0,1)----float
print("大于等于1且小于等于3之间的整数: ", random.randint(1, 3))  # [1,3]
print("大于等于1且小于3之间的整数: ", random.randrange(1, 3))  # [1,3)
print("1或者23或者[4,5]: ", random.choice([1, '23', [4, 5]]))  # 1或者23或者[4,5]
print("列表元素任意2个组合: ", random.sample([1, '23', [4, 5]], 2))  # 列表元素任意2个组合
print("大于1小于3的小数: ", random.uniform(1, 3))  # 大于1小于3的小数,如1.927109612082716
item = [1, 3, 5, 7, 9]
random.shuffle(item)  # 打乱item的顺序,相当于"洗牌"
print("打乱item的顺序,相当于'洗牌': ", item)
# 随机验证码
res = ''
for i in range(6):
    s1 = chr(random.randint(65, 90))  # 字母
    s2 = str(random.randint(0, 9))  # 数字
    res += random.choice([s1, s2])
print(res)

三、os模块

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
os.environ  获取系统环境变量
os.path.abspath(path)  返回path规范化的绝对路径
os.path.split(path)  将path分割成目录和文件名二元组返回
os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path)  返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小
os路径处理
#方式一:推荐使用
import os
#具体应用
import os,sys
possible_topdir = os.path.normpath(os.path.join(
    os.path.abspath(__file__),
    os.pardir, #上一级
    os.pardir,
    os.pardir
))
sys.path.insert(0,possible_topdir)


#方式二:不推荐使用
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
#  在Linux和Mac平台上,该函数会原样返回path,在windows平台上会将路径中所有字符转换为小写,并将所有斜杠转换为饭斜杠。
>>> os.path.normcase('c:/windows\\system32\\')   
'c:\\windows\\system32\\'   
   

#规范化路径,如..和/
os.path.normpath('c://windows\\System32\\../Temp/')   
'c:\\windows\\Temp'   

a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..'
print(os.path.normpath(a))
/Users/jieli/test1

四、sys模块

  1. 基础函数功能说明
1 sys.argv           命令行参数List,第一个元素是程序本身路径
2 sys.exit(n)        退出程序,正常退出时exit(0)
3 sys.version        获取Python解释程序的版本信息
4 sys.maxint         最大的Int值
5 sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
6 sys.platform       返回操作系统平台名称
  1. python test.py 参数, 运行时候传递与接收参数, 实现: cp 源文件路径, 目标文件路径
# 需求: 在python test.py 的时候传一些参数, 如何拿到这个参数
import sys
# 获取解释器传入的参数, 在程序中就可以按照索引取出想要的参数值
print(sys.argv)  # ['test.py', '1', '2', '2']

# 应用需求: 写一个程序, 完成文件copy
# 原来解决方式
# src_file = 'C:/project/code/insertdata/read_test.txt'.strip()
# dst_file = 'C:/project/code/insertdata/read_test1.txt'.strip()

src_file = input('源文件路径:').strip()
dst_file = input('目标文件路径:').strip()

with open(r'%s'%src_file, mode='rb') as read_f, open(r'%s'%dst_file, mode='wb') as write_f:
    for line in read_f:
        write_f.write(line)

# 新解决办法
res = sys.argv
src_file = res[1]
dst_file = res[2]

with open(r'%s'%src_file, mode='rb') as read_f, open(r'%s'%dst_file, mode='wb') as write_f:
    for line in read_f:
        write_f.write(line)
  1. python打印进度条
import time

# 指定宽度
print('[%-15s]' %'#') # -:左对齐, 固定宽度50
print('[%-15s]' %'##')
print('[%-15s]' %'###')
print('[%-15s]' %'####')
res = ''
for i in range(50):
    res += '#'
    time.sleep(0.5)
    print('\r[%-50s]' % res, end='')  # 每次打印都是从行首

def progress(precent):
    if precent > 1:
        precent = 1
    res = int(precent * 50)
    print('\r[%-50s] %d%%' % ('#' * res, int(100 * precent)), end='')


recv_size = 0
total_size = 33333

while recv_size < total_size:
    time.sleep(0.2)  # 下载1024个字节的数据
    recv_size += 1024

    # 打印进度条
    precent = recv_size / total_size
    progress(precent)

五、shutil模块

  1. 文件的操作,主要看下面的知乎专栏

六、json&pickle模块(序列化和反序列化)

  • 序列化和反序列化
  1. 什么是序列化和反序列化
  • 内存中的数据类型 -----> 序列化 -----> 特定的格式(json或者pickle格式)

  • 内存中的数据类型 <----- 反序列化 <----- 特定的格式(json或者pickle格式)

  • 土办法:

    • {‘aaa’: 111} -----> 序列化str({‘aaa’: 111}) -----> “{‘aaa’: 111}”
    • {‘aaa’: 111} <----- 反序列化eval({‘aaa’: 111}) <----- “{‘aaa’: 111}”
  1. 为何要序列化
  • 序列化得到的结果=》特定格式的内容有两种用途
    • 可用于存储=》相当于存档
    • 传输给其他平台使用=》跨平台数据交互
      在这里插入图片描述
# python                java
#  列表    特定的格式    数组
import json

# 示例一
# 序列化
json_res = json.dumps([1, 'aaa', True, False])
print(json_res, type(json_res))

# 反序列化
l = json.loads(json_res)
print(l, type(l))

# 示范二
# 序列化结果写入文件的复杂方法
json_res = json.dumps([1, 'aaa', True, False])
with open('test.json', mode='wt', encoding='utf-8') as f:
    f.write(json_res)

# 序列化的结果写入文件的简单方法
with open('test.json', mode='wt', encoding='utf-8') as f:
    res = [1, 'aaa', True, False]
    json.dump(res, f)

# 从文件读取json格式的字符串的进行反序列化操作的复杂方法
with open('test.json', mode='rt', encoding='utf-8') as f:
    json_res = f.read()
    l = json.loads(json_res)
    print(l, type(l))

# 从文件读取json格式的字符串的进行反序列化操作的简单方法
with open('test.json', mode='rt', encoding='utf-8') as f:
    l = json.load(f)
    print(l, type(l))
  1. 强调
  • 针对用途一的特定格式:可以是一种专业的格式=》pickle只有python有
  • 针对用途二的特定格式:应该是一种通用, 能够被所有语言识别的格式=》json

七、shelvs模块

import pickle

dic = {'name': 'alvin', 'age': 23, 'sex': 'male'}

# 序列化
res = pickle.dumps(dic)
print(res, type(res))

# 反序列化
s = pickle.loads(res)
print(s, type(s))

八、xml模块和shelve

  1. xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。

xml的格式如下,就是通过<>节点来区别数据结构的:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

九、configparser模块

  • conf.init, 或者conf.cfg
# 注释
; 注释
[sections1]
k1=v1
is_admin=true
salary=31
age=18

[sections2]
k1 = v1
  • common/conf.py
# 加载某种格式的配置文件
import configparser

conf = configparser.ConfigParser()
conf.read('conf.cfg')

# 获取所有的section
print(conf.sections())

# 获取某一section下的所有配置项options
print(conf.options('sections1'))

# 获取items
print(conf.items('sections1'))

# 获取某一特定的值, 结果为字符串
res = conf.get('sections1', 'k1')
print(res, type(res))

# 获取某一特定的值, 结果为int
res = conf.getint('sections1', 'age')
print(res, type(res))

# 获取某一特定的值, 结果为boolean
res = conf.getboolean('sections1', 'is_admin')
print(res, type(res))

# 获取某一特定值的, 结果为float
res = conf.getfloat('sections1', 'salary')
print(res, type(res))

十、hashlib模块

  1. 什么叫hash:hash是一种算法

    • (3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算法接受传入的内容,经过运算得到一串hash值
  2. hash值的特点是:

    • Ⅰ 只要传入的内容一样,得到的hash值必然一样=====>要用明文传输密码文件完整性校验
    • Ⅱ不能由hash值返解成内容=======> 把密码做成hash值,不应该在网络传输明文密码
    • Ⅲ 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的
  3. hash的用途

    • 用途一: 特点Ⅱ用于密码的密文传输与验证
    • 用途二: 特点Ⅰ、Ⅲ用于文件完整性校验

在这里插入图片描述

  • 基本使用
import hashlib

# 如何用, 验证只要传入的内容一样,得到的hash值必然一样=
m = hashlib.md5()
m.update('hello'.encode('utf-8'))
m.update('zpp'.encode('utf-8'))
res = m.hexdigest()
print(res)

m1 = hashlib.md5('he'.encode('utf-8'))
m1.update('llo'.encode('utf-8'))
m1.update('zpp'.encode('utf-8'))
res = m1.hexdigest()
print(res)
  • 校验文件
# 校验文件的时候
# 方法一: 不推荐,如果文件过大
m.update('所有文件的内容')
m.hexdigest()

# 方法二: 推荐, 但是会占用资源, 所以随机取出一些行作为验证
f = open('a.txt', mode='rb')
f.seek()  # 设置随机种子
f.read(2000)
m.update('一行文件')
m.update('一行文件')
m.update('一行文件')
m.update('一行文件')
m.hexdigest()
  • 撞库获取明文密码
# 假设截获一个hash格式的密码passhash = 7635fbcd0d249f02f5558bf0eb241c04
passhash = '7635fbcd0d249f02f5558bf0eb241c04'
# 制作密码字段、一般网上有
passwds = ['zpp1234', 'zpp4567', 'z1234pp', 'zpp456']

dic = dict()
for p in passwds:
    res = hashlib.md5(p.encode('utf-8'))
    dic[p] = res.hexdigest()

# 模拟撞库得到密码
for k, v in dic.items():
    if v == passhash:
        print('撞库成功, 明文密码是:{0}'.format(k))
        break

  • 密码加盐,提升撞库成本
# 真正的密码是:zpp1234
# 在特定位置加上毫无相关的东西
# 加盐后的密码是: z我pp爱1234你

十一、suprocess模块

# 查看系统命令
import subprocess
# 正确
# obj = subprocess.Popen('dir', shell=True,
#                  stdout=subprocess.PIPE,  # 管道符, 输出到管道里
#                  stderr=subprocess.PIPE # 如果有错误, 输出到另外一个管道里
#                  )

# 错误
obj = subprocess.Popen('ls /root', shell=True,
                 stdout=subprocess.PIPE,  # 管道符, 输出到管道里
                 stderr=subprocess.PIPE # 如果有错误, 输出到另外一个管道里
                 )
print(obj)
# 打印正确输出的管道
print(obj.stdout.read().decode('gbk'))

# 打印错误输出的管道
print(obj.stderr.read().decode('gbk'))

十二、logging模块

  1. 基础日志的使用
# 日志模块的使用 logging
# start.py一般会放置在整个项目下
import logging

# 一:日志配置
logging.basicConfig(
    # 1、日志输出位置:1、终端 2、文件
    filename='../ATM/access.log',  # 不指定,默认打印到终端

    # 2、日志格式, 时间, 名字, 等级
    format='%(asctime)s - %(name)s : %(levelname)s -%(module)s:  %(message)s',

    # 3、时间格式
    datefmt='%Y-%m-%d %H:%M:%S %p',

    # 4、日志级别
    # critical => 50
    # error => 40
    # warning => 30
    # info => 20
    # debug => 10
    level=30,
)

# 二:输出日志
logging.debug('调试debug')  # 10
logging.info('消息info')  # 20
logging.warning('警告warn')  # 30
logging.error('错误error')  # 40
logging.critical('严重critical')  # 50
  1. settings模块
import os
import logging.config

# 1. 日志字典解释
# 可在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
# filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
# filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
# format:指定handler使用的日志显示格式。
# datefmt:指定日期时间格式。
# level:设置rootlogger(后边会讲解具体概念)的日志级别
# stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
#
# format参数中可能用到的格式化串:
# %(name)s Logger的名字
# %(levelno)s 数字形式的日志级别
# %(levelname)s 文本形式的日志级别
# %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
# %(filename)s 调用日志输出函数的模块的文件名
# %(module)s 调用日志输出函数的模块名
# %(funcName)s 调用日志输出函数的函数名
# %(lineno)d 调用日志输出函数的语句所在的代码行
# %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
# %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
# %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
# %(thread)d 线程ID。可能没有
# %(threadName)s 线程名。可能没有
# %(process)d 进程ID。可能没有
# %(message)s用户输出的消息

# 2. 定义三种日志输出格式 开始
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'

id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'

# 定义日志输出格式 结束

logfile_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目录

logfile_name = 'all2.log'  # log文件名

# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):
    os.mkdir(logfile_dir)

# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)

# 3. 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配置
        'll': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',  # 两层关卡
            'propagate': True,  # 向上(更高level的logger)传递
        },
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',  # 两层关卡
            'propagate': True,  # 向上(更高level的logger)传递
        }
    },
}


def load_my_logging_cfg():
    logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    logger = logging.getLogger(__name__)  # 生成一个log实例
    logger.info('It works!')  # 记录该文件的运行状态


if __name__ == '__main__':
    load_my_logging_cfg()

  1. start.py
# 接下来要做的是: 拿到日志的生产者即loggers来产生日志
# 拿到ll
# 但是需要先导入日志配置字典LOGGING_DIC
from conf import settings
import logging

from logging import config, getLogger

config.dictConfig(settings.LOGGING_DIC)
logger1 = getLogger('ll')  # 就是name, 如果相同的配置,找不到这个名字   默认从''查找
logger1.info('这是一条info日志')

logger2 = getLogger('终端日志')  # 就是name, 如果相同的配置,找不到这个名字   默认从''查找
logger1.info('这是一条info日志, 终端日志')
  1. 补充
  • 日志名的命名
    • 日志名是区别日志业务属性的一种非常重要的标识
  • 日志轮转
    • 就是settings的default,控制某个日志文件的大小, 超过以后自动新建一个日志, 将日志分开, 不存到一个文件中

十三、re模块

十四、猴子补丁

# 用自己的代码替换别
import os
import sys
import json
import ujson # 速度更快

# 条件, 很多py文件中已经用了这个模块,如何打补丁, 写在哪里可以更改每一个模块的, 临时打一个补丁
# 在入口文件, start.py处
def monkey_patch_json():
    json.__name__ = 'ujson'
    json.dumps = ujson.dumps
    json.loads = ujson.loads

monkey_patch_json()
# json.dumps() = 用更好的dumps功能
# json.loads() = 用更好的loads功能

if __name__ == '__main__':
    monkey_patch_json()
    print(monkey_patch_json.__name__)
    print(json.__name__)
    pass

相关连接(笔记来自于视频课程的归类整理):
[1]: https://www.bilibili.com/video/BV1QE41147hU?p=17
[2]: https://www.zhihu.com/column/c_1189883314197168128
[3]: https://www.cnblogs.com/linhaifeng/articles/6384466.html

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值