常用模块

常用模块

time和datatime模块

time

import time
#--------------------------我们先以当前时间为准,让大家快速认识三种形式的时间
print(time.time()) # 时间戳:1487130156.419527
print(time.strftime("%Y-%m-%d %X")) #格式化的时间字符串:'2017-02-15 11:40:53'

print(time.localtime()) #本地时区的struct_time
print(time.gmtime())    #UTC时区的struct_time
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)

datatime

print(datetime.datetime.now() )
print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分

random

import random
 
random.random()#(0,1)----float    大于0且小于1之间的小数
 
random.randint(1,3)  #[1,3]    大于等于1且小于等于3之间的整数
 
random.randrange(1,3) #[1,3)    大于等于1且小于3之间的整数
 
random.choice([1,'23',[4,5]])#1或者23或者[4,5]
 
random.sample([1,'23',[4,5]],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
def make_code(n):
    res=''
    for i in range(n):
        s1=chr(random.randint(65,90))
        s2=str(random.randint(0,9))
        res+=random.choice([s1,s2])
    return res

print(make_code(9))

os模块

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.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录



应用程序----》"ls /"
os.system("ls /")

规定:key与value必须都为字符串
os.environ['aaaaaaaaaa']='111'
print(os.environ)


print(os.path.dirname(r'/a/b/c/d.txt')) # /a/b/c
print(os.path.basename(r'/a/b/c/d.txt')) # d.txt


print(os.path.isfile(r'笔记.txt')) # False
print(os.path.isdir(r'aaa'))# False

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




# 获取根目录
BASE_DIR=os.path.dirname(os.path.dirname(__file__))
print(BASE_DIR)


# 在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())

sys模块


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       返回操作系统平台名称
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

    time.sleep(0.01) # 下载了1024个字节的数据

    recv_size+=1024 # recv_size=2048

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

json和pickle

序列化&反序列化
内存中的数据类型---->序列化---->特定的格式(json格式或者pickle格式)
内存中的数据类型<----反序列化<----特定的格式(json格式或者pickle格式)
为何要序列化
序列化得到结果=>特定的格式的内容有两种用途
1、可用于存储=》用于存档
2、传输给其他平台使用=》跨平台数据交互
python java
列表 特定的格式 数组

强调:
针对用途1的特定一格式:可是一种专用的格式=》pickle只有python可以识别
针对用途2的特定一格式:应该是一种通用、能够被所有语言识别的格式=》json

如何序列化与反序列化

import json
序列化
json_res=json.dumps([1,'aaa',True,False])
print(json_res,type(json_res)) # "[1, "aaa", true, false]"

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

将序列化的结果写入文件的简单方法
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:
    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]")
print(l[0])

猴子补丁
在入口处打猴子补丁


import json
import ujson

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

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

pickle模块

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

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

configparser

#text.ini
[section1]
k1 = v1
k2:v2
user=egon
age=18
is_admin=true
salary=31

[section2]
k1 = v1
#a.py
import configparser
config=configparser.ConfigParser()
config.read('text.ini')
print(config.options('section1'))
print(config.items('section1'))
print(config.get('section1','user'))
print(config.getint('section1','age'))
print(config.getfloat('section1','salary'))

#['k1', 'k2', 'user', 'age', 'is_admin', 'salary']
[('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')]
egon
18
31.0

hashlib

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

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

m=hashlib.md5()
m.update('hello'.encode('utf-8'))
m.update('world'.encode('utf-8'))
res=m.hexdigest() # 'helloworld'
print(res)
#fc5e038d38a57032085441e7fe7010b0

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

m=hashlib.md5()

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

subprocess 管道

import subprocess

obj=subprocess.Popen('echo 123 ; ls / ; ls /root',shell=True,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE,
                 )

print(obj)
res=obj.stdout.read()
print(res.decode('utf-8'))

err_res=obj.stderr.read()
print(err_res.decode('utf-8'))

logging 模块

1.1 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

1.2 日志配置字典
1.2.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用户输出的消息

1.2.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'

1.2.3 日志配置字典

LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        '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

​            'maxBytes': 1000,
​            '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配置
​        'kkk': {
​            'handlers': ['console','other'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
​            'level': 'DEBUG', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
​            'propagate': False,  # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
​        },
​        '终端提示': {
​            'handlers': ['console',],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
​            'level': 'DEBUG',  # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
​            'propagate': False,  # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
​        },
​        '': {
​            'handlers': ['default', ],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
​            'level': 'DEBUG',  # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
​            'propagate': False,  # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
​        },
​    },

}

1.2.3 产生日志文件
接下来要做的是:拿到日志的产生者即loggers来产生日志
第一个日志的产生者:kkk
第二个日志的产生者:bbb

但是需要先导入日志配置字典LOGGING_DIC

import settings
from logging import config,getLogger

config.dictConfig(settings.LOGGING_DIC)


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

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

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

logger4=getLogger('用户常规')
logger4.info('logger4产生的info日志')

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

2)日志轮转
日志记录着程序员运行过程中的关键信息

正则表达式(re模块)

import re

print(re.findall('\w','aAbc123_*()-='))
print(re.findall('\W','aAbc123_*()-= '))
print(re.findall('\s','aA\rbc\t\n12\f3_*()-= '))
print(re.findall('\S','aA\rbc\t\n12\f3_*()-= '))
print(re.findall('\d','aA\rbc\t\n12\f3_*()-= '))
print(re.findall('\D','aA\rbc\t\n12\f3_*()-= '))
print(re.findall('\D','aA\rbc\t\n12\f3_*()-= '))
print(re.findall('\Aalex',' alexis alex sb'))
                         alex
print(re.findall('sb\Z',' alexis alexsb sb'))
                                      sb\Z
print(re.findall('sb\Z',"""alex
alexis
alex
sb
"""))

print(re.findall('^alex','alexis alex sb'))
print(re.findall('sb$','alexis alex sb'))
print(re.findall('sb$',"""alex
alexis
alex
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"))
                                                                  \d+\.?\d*                                      \d+\.?\d+


[]匹配指定字符一个
print(re.findall('a\db','a1111111b a3b a4b a9b aXb a b a\nb',re.DOTALL))
print(re.findall('a[501234]b','a1111111b a3b a4b a9b aXb a b a\nb',re.DOTALL))
print(re.findall('a[0-5]b','a1111111b a3b a1b a0b a4b a9b aXb a b a\nb',re.DOTALL))
print(re.findall('a[0-9a-zA-Z]b','a1111111b axb a3b a1b a0b a4b a9b aXb a b a\nb',re.DOTALL))

print(re.findall('a[^0-9a-zA-Z]b','a1111111b axb a3b a1b a0b a4b a9b aXb a b a\nb',re.DOTALL))
print(re.findall('a-b','a-b aXb a b a\nb',re.DOTALL))
print(re.findall('a[-0-9\n]b','a-b a0b a1b a8b aXb a b a\nb',re.DOTALL))
posted @ 2020-03-30 15:28  小子,你摊上事了  阅读(77)  评论(0编辑  收藏  举报