day14~16 (常用模块)

让人想犯罪 __ 提交于 2020-04-06 07:29:17

# 时间模块优先掌握的操作

# 一:time

# 时间分为三种格式:
# 1、时间戳(timestape):从1970年到现在经过的秒数
#    作用:用于时间间隔的计算

# print(time.time())

# 2、格式化的时间字符串(format string): 按照某种格式显示的时间:2020-03-30 11:11:11
#    作用:用于展示时间

# time.strftime('%Y-%m-%d %H:%M:%S %p')
# time.strftime('%Y-%m-%d %X')

# 3、结构化的时间(struct_time)
#    作用:用于单独获取时间的某一部分

# res=time.localtime()  # 本地时区的struct_time
# tm_year=, tm_mon=, tm_mday=, tm_hou=, tm_min=, tm_sec=, tm_wday(一年中第几周)=, tm_yday(一年中第几天)=, tm_isdst(夏令时)=
# print(res.tm_yday)

# time.gmtime   # UTC时区的struct_time

# 二:datetime
import datetime

# print(datetime.datetime.now())  -> 2020-03-30 14:52:31.833672
# 作用:用来进行时间运算

# print(datetime.datetime.now() + datetime.timedelta(days=3))   #datetime.timedelta 用来盛放需要增加或减少的时间
# print(datetime.datetime.now() + datetime.timedelta(weeks=1))


# 时间模块需要掌握的操作

# 1、时间格式的转换

# struct_time->时间戳
import time

# s_time=time.localtime()
# print(time.mktime(s_time))

# 时间戳->struct_time
# tp_time=time.time()
# print(time.localtime(tp_time))
# print(time.gmtime(333333333))

# struct_time->格式化的字符串形式的时间
# s_time=time.localtime()
# print(time.strftime('%Y-%m-%d %H:%M:%S',s_time))

# 格式化字符形式的时间->struct time
# print(time.strptime('1988-03-03 11:11:11','%Y-%m-%d %H:%M:%S'))


# format string<------>timestamp  (重点掌握)
# '1988-03-03 11:11:11'+7

# format string--->struct_time--->timestamp
# struct_time=time.strptime('1988-03-03 11:11:11','%Y-%m-%d %H:%M:%S')
# timestamp=time.mktime(struct_time)+7*86400
# print(timestamp)

# format string<---struct_time<---timestamp
# res=time.strftime('%Y-%m-%d %X',time.localtime(timestamp))
# print(res)

# time.sleep(3)

# 了解知识
# import time
# print(time.asctime())  把一个表示时间的元祖或struct_time表示为:sun jun 20 23:21:05 1993 这种形式

# import datetime
# print(datetime.datetime.now())
# print(datetime.datetime.utcnow()) # 世界标准时间

print(datetime.datetime.fromtimestamp(333333)) # 时间戳直接转换为格式字符形式的日期

# import random  随机取数
# print(random.random()) #(0,1)----float    大于0且小于1之间的小数
# print(random.randint(1, 3))  # [1,3]    大于等于1且小于等于3之间的整数
# print(random.randrange(1, 3))  # [1,3)    大于等于1且小于3之间的整数
# print(random.choice([111, 'aaa', [4, 5]]))  # 1或者23或者[4,5]
# print(random.sample([111, 'aaa', 'ccc','ddd'],2))  # 列表元素任意2个组合
# print(random.uniform(1, 3))  # 大于1小于3的小数,如1.927109612082716
# item = [1, 3, 5, 7, 9]
# random.shuffle(item)  # 打乱item的顺序,相当于"洗牌"
# print(item)

# 应用:随机验证码

# import random
#
# res=''
# for i in range(6):
#     从26大写字母中随机取出一个=chr(random.randint(65,90))  chr[65]~chr[90] 参考的ASCII码表,对应A~Z
#     从10个数字中随机取出一个=str(random.randint(0,9))
#
#     随机字符=random.choice([从26大写字母中随机取出一个,从10个数字中随机取出一个])
#     res+=随机字符


import random


def make_code(size=4):
    res = ''
    for i in range(size):
        s1 = chr(random.randint(65, 90))
        s2 = str(random.randint(0, 9))
        res += random.choice([s1, s2])
    return res


print(make_code(6))

# import os

# 获取某一个文件夹下所有的子文件以及子文件夹的名字
# res=os.listdir('.')
# print(res)

# 返回path的大小
# size=os.path.getsize(r'/Users/linhaifeng/PycharmProjects/s14/day22/01 时间模块.py')
# print(size)

# os.remove()  删除一个文件
# os.rename("oldname","newname")  重命名文件/目录


# 运行系统命令:应用程序向操作系统发送系统调用运行相关命令
# os.system("dir r'C:\\a\b'")

# 得到一个字典,规定:key与value必须都为字符串
# os.environ['aaaaaaaaaa']='111'  获取系统环境变量,范围更广
# print(os.environ)


# print(os.path.dirname(r'/a/b/c/d.txt'))
# print(os.path.basename(r'/a/b/c/d.txt')) 返回path最后的文件名


# print(os.path.isfile(r'笔记.txt')) 当前文件夹下是否存在文件
# print(os.path.isdir(r'aaa'))  当前文件夹下是否存在文件夹

# print(os.path.join('a','/','b','c','d')) path拼接


# 三种获得上上一层文件夹路径的方法
# BASE_DIR=os.path.dirname(os.path.dirname(__file__)) 推荐这种
# print(BASE_DIR)

# normpath 规范化路径
# BASE_DIR=os.path.normpath(os.path.join(__file__,#     '..',#     '..'# ))


# 在python3.5之后,推出了一个新的模块pathlib
# from pathlib import Path
# res = Path(__file__).parent.parent
# print(res)


# res=Path('/a/b/c') / 'd/e.txt'
# print(res)

# print(res.resolve())


# import sys

# python3.8 run.py 1 2 3
# sys.argv 命令行参数别表,第一个元素是路径本身,用来接收外面传进来的值,也就是获取解释器后的参数值
# print(sys.argv)

# 【案例  文件copy脚本】

# import os
# src_file=sys.argv[1]
# dst_file=sys.argv[2]
# def copy_file():
#   if not os.path.isfile(src_file):
#       print('请输入正确的源文件路径')
#       rutern
#   if not os.path.isfile(dst_file):
#       print('请输入正确的目标文件路径')
#      return
#   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)

# python3.8 run.py src_file dst_file

#
# 【案例:模拟下载及打印进度条】

import time


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


recv_size = 0
total_size = 1025011

while recv_size < total_size:
    time.sleep(0.01)
    recv_size += 1024

    # 打印进度条
    percent = recv_size / total_size  # 1024 / 333333
    progress(percent)

# # shutil(了解)
# import shutil
#
# shutil.copyfileobj(open('old.xml', 'r'), open('new.xml', 'w'))
# # 将文件内容拷贝到另一个文件中
#
# shutil.copyfile('f1.log', 'f2.log')  # 目标文件无需存在 拷贝文件
#
# shutil.copymode('f1.log', 'f2.log')  # 目标文件必须存在 仅拷贝权限。内容、组、用户均不变
#
# shutil.copystat('f1.log', 'f2.log')  # 目标文件必须存在           仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
#
# shutil.copy('f1.log', 'f2.log')
# # 拷贝文件和权限
#
# shutil.copy2('f1.log', 'f2.log')
# # 拷贝文件和状态信息
#
# shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
# # 目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除            递归的去拷贝文件夹
#
# shutil.rmtree('folder1')
# # 递归的去删除文件
#
# shutil.move('folder1', 'folder3')
# # 递归的去移动文件,它类似mv命令,其实就是重命名。
#
#
# # 将 /data 下的文件打包放置当前程序目录
# import shutil
#
# ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
#
# # 将 /data下的文件打包放置 /tmp/目录
# import shutil
#
# ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
# #
# # shutil
# # 对压缩包的处理是调用
# # ZipFile
# # 和
# # TarFile
# # 两个模块来进行的,详细:

# import tarfile
#
# # 压缩
# t = tarfile.open('/tmp/egon.tar', 'w')
# t.add('/test1/a.py', arcname='a.bak')
# t.add('/test1/b.py', arcname='b.bak')
# t.close()

# 解压
t = tarfile.open('/tmp/egon.tar', 'r')
t.extractall('/egon')
t.close()

# tarfile压缩解压缩
View Code

二. 序列化

一、json 与 pickle 模块

# 1、什么是序列化&反序列化

#序列化:把对象从内存中变成可存储或者传输的类型发生的过程

#反序列化:把这种序列化得到的类型再转变成之前的类型

 

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

# 土办法:
# {'aaa':111}--->序列化str({'aaa':111})----->"{'aaa':111}"
# {'aaa':111}<---反序列化eval("{'aaa':111}")<-----"{'aaa':111}"

# 2、为何要序列化
# 序列化得到的结果=>特定的格式的内容有两种用途
# 1、可用于存储=》用于存档
# 2、传输给其他平台使用=》跨平台数据交互

# 强调:
# 存储用的特定格式:专用的格式=》pickle,只有python可以识别
# 传输用的特定格式:一种通用、能够被所有语言识别的格式=》json


# 3、如何序列化与反序列化
# 示范1
# import json
# # 序列化
# json_res=json.dumps([1,'aaa',True,False])

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

 

# 示范2:
import json

# 序列化的结果写入文件的复杂方法
# json_res=json.dumps([1,'aaa',True,False])
#     print(json_res,type(json_res)) # "[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:
# json.dump([1,'aaa',True,False],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))


# json验证: json格式兼容的是所有语言通用的数据类型,不能识别某一语言的所独有的类型
# json.dumps({1,2,3,4,5})  #集合读不出来

# json强调:一定要搞清楚json格式,不要与python混淆
# l=json.loads('[1, "aaa", true, false]')
# l=json.loads("[1,1.3,true,'aaa', true, false]")   #json 不识别单引号
# print(l[0])

# 了解

#在python解释器2.7与3.6之后都可以json.loads(bytes类型),唯独3.5不可以

# l = json.loads(b'[1, "aaa", true, false]')
# print(l, type(l))

# with open('test.json',mode='rb') as f:
# l=json.load(f)


# res=json.dumps({'name':'哈哈哈'})   # 中文字符序列化后的形式=>   "\u54c8\u54c8\u54c8"
# print(res,type(res))

 

# 4、猴子补丁
# 在入口处打猴子补丁
# import json
# import ujson

# def monkey_patch_json():
#   json.__name__ = 'ujson'
#   json.dumps = ujson.dumps
#   json.loads = ujson.loads

# monkey_patch_json() # 在入口文件处运行


# import ujson as json # 不行,导入的还是ujson

 

# 5.pickle模块
import pickle
# res=pickle.dumps({1,2,3,4,5})
# print(res,type(res))

# s=pickle.loads(res)
# print(s,type(s))

 

二、configparser 模块

用configparser 对settings文件进行读取

文件格式如下:

[section1]

k1 =v1

[section2]

k2 : v2

age = 18

 

import configparser

# 1、获取sections
# print(config.sections())

# 2、获取某一section下的所有options
# print(config.options('section1'))

# 3、获取items
# print(config.items('section1'))

# 4、获取某一sections下指定的options
# res=config.get('section1','user')
# print(res,type(res))

 

三、hashlib 模块

# 1、什么是哈希hash
# hash一类算法,该算法接受传入的内容,经过运算得到一串hash值
# hash值的特点:
#I 只要传入的内容一样,得到的hash值必然一样
#II 不能由hash值返解成内容
#III 不管传入的内容有多大,只要使用的hash算法不变,得到的hash值长度是一定

# 2、hash的用途
# 用途1:特点II用于密码密文传输与验证
# 用途2:特点I、III用于文件完整性校验

# 3、如何用
# import hashlib
#
# m=hashlib.md5()
# m.update('hello'.encode('utf-8'))   # windows 系统默认是GBK
# m.update('world'.encode('utf-8'))
# res=m.hexdigest() # 'helloworld'
# print(res)

# 模拟撞库
# cryptograph='aee949757a2e698417463d47acac93df'
# import hashlib

# # 制作密码字段
 passwds=[
  'alex3714',
  'alex1313',
  'alex94139413',
  'alex123456',
  '123456alex',
  'a123lex',
  ]

# dic={}
# for p in passwds:
#    res=hashlib.md5(p.encode('utf-8'))
#    dic[p]=res.hexdigest()
#
# # 模拟撞库得到密码
# for k,v in dic.items():
#    if v == cryptograph:
#    print('撞库成功,明文密码是:%s' %k)
#   break


# 提升撞库的成本=>密码加盐
import hashlib

m=hashlib.md5()

m.update('天王'.encode('utf-8'))
m.update('alex3714'.encode('utf-8'))
m.update('盖地虎'.encode('utf-8'))
print(m.hexdigest())

 

# 文件的完整性校验

# m.update(文件所有的内容)
# m.hexdigest()

# with open('a.txt',mode='rb') as f:
#   f.seek(0,10)
#   f.read(10) 

 

四、subprocess 模块

import subprocess

obj=subprocess.Popen('路径',shell=True,
stdout=subprocess.PIPE,stderr=subprocess.PIPE,)   # stdout:标准正确输出   pipe:管道  stderr:错误输出

# print(obj)
# res=obj.stdout.read()
# print(res.decode('gbk'))

err_res=obj.stderr.read()
View Code

三 日志 re

# 三
# 一、logging 模块

import logging

logging.basicConfig(
    # 1、日志输出位置:1、终端 2、文件
    filename='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=10,
)

logging.debug('调试debug') # 10
logging.info('消息info')   # 20
logging.warning('警告warn')# 30
logging.error('egon提现失败') # 40
logging.critical('严重critical') # 50

"""
日志配置字典LOGGING_DIC
"""
# 1、定义三种日志输出格式,日志中可能用到的格式化串如下
# %(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、强调:其中的%(name)s为getlogger时指定的名字
standard_format = '%(asctime)s - %(threadName)s:%(thread)d - 日志名字:%(name)s - %(filename)s:%(lineno)d -' \
                  '%(levelname)s - %(message)s'

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

test_format = '%(asctime)s] %(message)s'

# 3、日志配置字典
LOGGING_DIC = {
    'version': 1,  #版本
    'disable_existing_loggers': False,   #禁用现有的记录器
    'formatters': {                      #定制不同的日志格式对象,绑定给不同的handler对象使用
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
        'test': {
            'format': test_format
        },
    },
    'filters': {},                 #过滤日志的对象
    # handlers是日志的接收者,不同的handler会将日志输出到不同的位置
    'handlers': {
        #打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,日志轮转
            'maxBytes': 1024*1024*5,  # 日志大小 5M
            'backupCount': 5,  # 备份计数
            'filename': 'a1.log',  # os.path.join(os.path.dirname(os.path.dirname(__file__)),'log','a2.log')
            'encoding': 'utf-8',
            'formatter': 'standard',
        },
        #打印到文件的日志,收集info及以上的日志
        'other': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # 保存到文件
            'filename': 'a2.log', # os.path.join(os.path.dirname(os.path.dirname(__file__)),'log','a2.log')
            'encoding': 'utf-8',
            'formatter': 'test',

        },
    },
    # loggers是日志的产生者,产生的日志会传递给handler然后控制输出
    'loggers': {
        #logging.getLogger(__name__)拿到的logger配置  #name是loggers子子典当中的key
        'kkk': {
            'handlers': ['console','other'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
            'propagate': False,  # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
        },
        '终端提示': {
            'handlers': ['console',], 
            'level': 'DEBUG',  
            'propagate': False,  
        },
        '': {
            'handlers': ['default', ], 
            'level': 'DEBUG',  
            'propagate': False,  
        },
    },
}

# 4、应用

import settings

# 1、logging是一个包,需要使用其下的config、getLogger,可以如下导入
# from logging import config
# from logging import getLogger

# 2、也可以使用如下导入
import logging.config # 这样连同logging.getLogger都一起导入了,然后使用前缀logging.config.

# 3、加载配置
logging.config.dictConfig(settings.LOGGING_DIC)

# 4、拿到日志的产生者即loggers来产生日志

# logger1=getLogger('kkk')
# logger1.info('这是一条info日志')

# logger2=getLogger('终端提示')
# logger2.info('logger2产生的info日志')

# logger3=getLogger('用户交易')
# logger3.info('logger3产生的info日志')

# logger4=getLogger('用户常规')  #当getLogger取不到对象是,默认使用key=''的配置
# logger4.info('logger4产生的info日志')


# 5、补充两个重要额知识
# 1、日志名的命名
#    日志名是区别日志业务归属的一种非常重要的标识

# 2、日志轮转
#    日志记录着程序员运行过程中的关键信息,所以不能随意删,为了避免放在同一个日志文件中造成文件过大,加载缓慢,
#    需要一种设定,超出限制后会将之前的内容写到另一个文件中,当前文件只剩新内容
#     (实际上老文件是做了重命名用来保存老内容,然后再生成一个新的空文件,命名为原名,保存新内容)


# 二、re 模块




import re

# print(re.findall('\Aalex',' alexis alex sb')) ==>[] 字符串开头是空格
#                       
# print(re.findall('sb\Z',' alexis alexsb sb'))
#                                      
# print(re.findall('sb\Z',"""alex
# alexis
# alex
# sb
# """)) ==> [] 只匹配到换行前的结束字符串

# print(re.findall('sb$',"""alex
# alexis
# alex
# sb
# """)) ==> ['sb']

# print(re.findall('^alex$','alexis alex sb'))
# print(re.findall('^alex$','al       ex'))
# print(re.findall('^alex$','alex'))   ==>混用时必须完全一样才能匹配

# 重复匹配:| . | * | ? | .* | .*? | + | {n,m} |

# 1、.:匹配除了\n之外任意一个字符,指定re.DOTALL之后才能匹配换行符
# print(re.findall('a.b','a1b a2b a b abbbb a\nb a\tb a*b'))
#                                                   a.b
# ['a1b','a2b','a b','abb','a\tb','a*b']
# print(re.findall('a.b','a1b a2b a b abbbb a\nb a\tb a*b',re.DOTALL))

# 2、*:左侧字符重复0次或无穷次,性格贪婪
# print(re.findall('ab*','a ab abb abbbbbbbb bbbbbbbb'))
#                                                ab*
#['a','ab','abb','abbbbbbbb']

# 3、+:左侧字符重复1次或无穷次,性格贪婪
# print(re.findall('ab+','a ab abb abbbbbbbb bbbbbbbb'))
#                         ab+

# 4、?:左侧字符重复0次或1次,性格贪婪
# print(re.findall('ab?','a ab abb abbbbbbbb bbbbbbbb'))
#                                                ab?
# ['a','ab','ab','ab']

# 5、{n,m}:左侧字符重复n次到m次,性格贪婪
# {0,} => *
# {1,} => +
# {0,1} => ?
# {n}单独一个n代表只出现n次,多一次不行少一次也不行

# print(re.findall('ab{2,5}','a ab abb abbb abbbb abbbbbbbb bbbbbbbb'))
#                                                           ab{2,5}
# ['abb','abbb','abbbb','abbbbb]

# print(re.findall('\d+\.?\d*',"asdfasdf123as1111111.123dfa12adsf1asdf3"))



# []匹配指定字符一个
# print(re.findall('a\db','a1111111b a3b a4b a9b aXb a b a\nb',re.DOTALL)) ['a3b', 'a4b', 'a9b']
# print(re.findall('a[501234]b','a1111111b a3b a4b a9b aXb a b a\nb',re.DOTALL))  ['a3b', 'a4b']
# print(re.findall('a[0-9a-zA-Z]b','a1111111b axb a3b a1b  a b a\nb',re.DOTALL)) ['axb', 'a3b', 'a1b', ]
# print(re.findall('a[^0-9a-zA-Z]b','a1111111b axb a3b a1b a0b a4b a9b aXb a b a\nb',re.DOTALL)) ['a b', 'a\nb'] ^表示非
# print(re.findall('a[-0-9\n]b','a-b a0b a1b a8b aXb a b a\nb',re.DOTALL)) ['a-b', 'a0b', 'a1b', 'a8b', 'a\nb']
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!