标签:lod 概念 dom wap 权限 SHA256 IV 传参 形式
import time print(time.time()) print(time.strftime("%Y-%m-%d %X")) print(time.localtime()) print(time.gmtime())
import time,datetime print(datetime.datetime.now()) print(datetime.date.fromtimestamp(time.time())) print(datetime.datetime.now()) print(datetime.datetime.now() + datetime.timedelta(hours=4)) c_time = datetime.datetime.now() print(c_time.replace(minute=3,hour=2))
import random print(random.random()) #---float 大于0且小于1之间的小数 print(random.randint(1,3)) #大于等于1且小于等于3之间的整数 print(random.randrange(1,3)) #大于等于1且小于3之间的整数 print(random.choice([1,‘23‘,[4,5]])) #1或者23或者[4,5] print(random.sample([1,‘23‘,[4,5]],2)) #列表元素任意2个组合 print(random.uniform(1,3)) #大于1小于3的小数 item=[1,3,5,7,9] print(random.shuffle(item)) #打乱item的顺序,相当于洗牌
#生成随机验证码 import random def make_code(n): res=‘‘ for i in range(n): s1=chr(random.randint(65,90)) s2=chr(random.randint(0,9)) res +=random.choice([s1,s2]) return res print(make_code(9))
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__))))
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 返回操作系统平台名称
ps: 打印进度条:
#=========知识储备========== #进度条的效果 [# ] [## ] [### ] [#### ] #指定宽度 print(‘[%-15s]‘ %‘#‘) print(‘[%-15s]‘ %‘##‘) print(‘[%-15s]‘ %‘###‘) print(‘[%-15s]‘ %‘####‘) #打印% print(‘%s%%‘ %(100)) #第二个%号代表取消第一个%的特殊意义 #可传参来控制宽度 print(‘[%%-%ds]‘ %50) #[%-50s] print((‘[%%-%ds]‘ %50) %‘#‘) print((‘[%%-%ds]‘ %50) %‘##‘) print((‘[%%-%ds]‘ %50) %‘###‘) #=========实现打印进度条函数========== import sys import time def progress(percent,width=50): if percent >= 1: percent=1 show_str=(‘[%%-%ds]‘ %width) %(int(width*percent)*‘#‘) print(‘\r%s %d%%‘ %(show_str,int(100*percent)),file=sys.stdout,flush=True,end=‘‘) #=========应用========== data_size=1025 recv_size=0 while recv_size < data_size: time.sleep(0.1) #模拟数据的传输延迟 recv_size+=1024 #每次收1024 percent=recv_size/data_size #接收的比例 progress(percent,width=70) #进度条的宽度70
shutil.copyfileobj(fsrc,fdst[,length]) 将文件内容拷贝到另一个文件中
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.copy(src,dest) 拷贝文件和权限
import shutil
shutil.copy(‘f1.log‘,‘f2.log‘)
shutil.copy2(src,dest) 拷贝文件和状态信息
import shutil1
shutil1.copy2(‘f1.log‘,‘f2.log‘)
shutil.ignore_patterns(*patterns)
shutil.copytree(src,dest,symlinks=False,ignore=None) 递归的去拷贝文件夹
import shutil
shutil.copytree(‘f1‘,‘f2‘,symlinks=Ture,ignore=shutil.ignore_patterns(‘*.pyc‘,‘tmp*‘)) #目标目录不能存在,注意对floder2目录父级目录要有可写权限,ignore的意思是排除
拷贝软链接:
import shutil
shutil.copytree(‘f1‘,‘f2‘,symlinks=True,ignore=shutil.ignore_patterns(‘*.pyc‘,‘tmp*‘)) #通常的拷贝就是把软连接拷贝成硬连接,即对待软连接来说,创建新的文件
shutil.rmtree(path[,ignore_errorsp[,onerror]]) #递推的去删除文件
import shutil
shutil.rmtree(‘folder1‘)
shutil.move(src,dest)
import shutil
shutil.move(‘folder1‘,‘folder3‘)
shutil.make_archive(base_name,format,......)
创建压缩包并返回文件路径,例如:zip,tar
创建压缩包并返回文件路径,例如:zip,tar
>> base.name: 压缩包的文件名,也可以是压缩包的路径。只有文件名时,则保存至当前目录,否则保存至指定路径,如data_bak ==>保存至当前路径, 如/tmp/data_bak ==>保存至/tmp/
>> format : 压缩包种类,"zip", "tar", "bztar","gztar"
>> root_dir: 要压缩的文件夹路径(默认当前目录)
>>owner: 用户,默认当前用户
>>group : 组,默认当前组
>>logger:用于记录日志,通常是logging.Logger 对象
#将 /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两个模块来进行的,详细:
# zipfile 压缩解压缩
import zipfile
#压缩
z=zipfile.ZipFile(‘laxi.zip‘,‘w‘)
z.write(‘a.log‘)
z.write(‘data.data‘)
z.close()
#解压
z=zipfile.ZipFile(‘laxi.zip‘,‘r‘)
z.extractall(path=‘.‘)
z.close()
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()
import json
x="[null,true,false,1]"
print(eval(x)) #报错无法解析null类型,而json就可以
print(json.loads(x))
json 和python的内置数据如下表:
JSON |
Python |
{} | dict |
[] | list |
"string" | str |
1234.56 | int/float |
true/false | True/False |
null | None |
shelve 模块比pickle模块简单,只是一个open函数,返回类似字典的对象,可读可写,key必须为字符串,而值可以是python所支持的数据类型
import shelve
f=shelve.open(r ‘ sheve.txt‘)
print(f[‘syu1_info‘][‘hobby‘])
f.close()
xml 是实现不同语言或程序之前进行数据交换的协议,跟json 差不多,但json 使用起来更简单,不过,古时候,在json还没有诞生的黑暗时代,大家只能选择用xml呀,至今很多传统的金融行业的很多系统的 接口还主要是xml,xml的格式是通过<>节点来区别数据结构的,xml协议在各个语言里面都是支持的,再python中可以用一下模块操作xml:
print(root.iter(‘year‘)) #全文搜索
print(root.find(‘country‘)) #在root的子节点找,只找一个
print(root.findall(‘country‘)) #在root 的子节点找,找所有
在country内添加(append)节点year2
import xml.etree.ElementTree as ET
tree=ET.parse("a.xml")
root=tree.getroot()
for country in root.findall(‘country‘):
for year in country.findall(‘year‘)
if int(year.text) >2000:
year2=ET.Element(‘year2‘)
year2.text=‘新年‘
year2.attrib={‘update‘:‘yes‘}
country.append(year2) #往country节点下面添加子节点
tree.write(‘a.xml.swap‘)
读取代码:
import configparser config=configparser.ConfigParser() config.read(‘a.cfg‘) #查看所有的标题 res=config.sections() #[‘section1‘, ‘section2‘] print(res) #查看标题section1下所有key=value的key options=config.options(‘section1‘) print(options) #[‘k1‘, ‘k2‘, ‘user‘, ‘age‘, ‘is_admin‘, ‘salary‘] #查看标题section1下所有key=value的(key,value)格式 item_list=config.items(‘section1‘) print(item_list) #[(‘k1‘, ‘v1‘), (‘k2‘, ‘v2‘), (‘user‘, ‘egon‘), (‘age‘, ‘18‘), (‘is_admin‘, ‘true‘), (‘salary‘, ‘31‘)] #查看标题section1下user的值=>字符串格式 val=config.get(‘section1‘,‘user‘) print(val) #egon #查看标题section1下age的值=>整数格式 val1=config.getint(‘section1‘,‘age‘) print(val1) #18 #查看标题section1下is_admin的值=>布尔值格式 val2=config.getboolean(‘section1‘,‘is_admin‘) print(val2) #True #查看标题section1下salary的值=>浮点型格式 val3=config.getfloat(‘section1‘,‘salary‘) print(val3) #31.0
改写代码:
import configparser config=configparser.ConfigParser() config.read(‘a.cfg‘,encoding=‘utf-8‘) #删除整个标题section2 config.remove_section(‘section2‘) #删除标题section1下的某个k1和k2 config.remove_option(‘section1‘,‘k1‘) config.remove_option(‘section1‘,‘k2‘) #判断是否存在某个标题 print(config.has_section(‘section1‘)) #判断标题section1下是否有user print(config.has_option(‘section1‘,‘‘)) #添加一个标题 config.add_section(‘egon‘) #在标题egon下添加name=egon,age=18的配置 config.set(‘egon‘,‘name‘,‘egon‘) config.set(‘egon‘,‘age‘,18) #报错,必须是字符串 #最后将修改的内容写入文件,完成最终的修改 config.write(open(‘a.cfg‘,‘w‘))
hash算法就像一座工厂,工厂接收你送来的原材料(可以m.update()为工厂运送原材料) ,经过加工返回的产品就是hash值
import hashlib
m=hashlib.md5() #m=hashlib.sha256()
m.update(‘hello‘.encode(‘utf8‘))
print(m.hexdigest())
m.update(‘alvin‘.encode(‘utf8‘))
print(m.hexdigest())
m2=hashlib.md5()
m2=hashlib.md5()
m2.update(‘helloalvin‘.encode(‘utf8‘))
print(m2.hexdigest())
python 还有一个hmac模块,它内部对我们的创建key和内容进行进一步的处理然后再加密
import hmac
h=hmac.new(‘alvin‘.encode(‘utf8‘))
h.update(‘hello‘.encode(‘utf8‘))
print(h.hexdigest())
要想保证hmac最终结果一致,必须保证:
1:hmac.new括号内指定的初始key一样
2:无论update多少次,校验的内容累加到一起是一样的内容
import hmac
h1=hamc.new(b‘egon‘)
h1.update(b‘hello‘)
h1.update(b‘world‘)
print(h1.hexdigest())
h2=hmac.new(b‘egon‘)
h2.update(b‘helloworld‘)
print(h2.hexdigest())
h3=hmac.new(b‘egonhelloworle‘)
print(h3.hexdigest())
1 import subprocess 2 3 ‘‘‘ 4 sh-3.2# ls /Users/egon/Desktop |grep txt$ 5 mysql.txt 6 tt.txt 7 事物.txt 8 ‘‘‘ 9 10 res1=subprocess.Popen(‘ls /Users/jieli/Desktop‘,shell=True,stdout=subprocess.PIPE) 11 res=subprocess.Popen(‘grep txt$‘,shell=True,stdin=res1.stdout, 12 stdout=subprocess.PIPE) 13 14 print(res.stdout.read().decode(‘utf-8‘)) 15 16 17 #等同于上面,但是上面的优势在于,一个数据流可以和另外一个数据流交互,可以通过爬虫得到结果然后交给grep 18 res1=subprocess.Popen(‘ls /Users/jieli/Desktop |grep txt$‘,shell=True,stdout=subprocess.PIPE) 19 print(res1.stdout.read().decode(‘utf-8‘)) 20 21 22 #windows下: 23 # dir | findstr ‘test*‘ 24 # dir | findstr ‘txt$‘ 25 import subprocess 26 res1=subprocess.Popen(r‘dir C:\Users\Administrator\PycharmProjects\test\函数备课‘,shell=True,stdout=subprocess.PIPE) 27 res=subprocess.Popen(‘findstr test*‘,shell=True,stdin=res1.stdout, 28 stdout=subprocess.PIPE) 29 30 print(res.stdout.read().decode(‘gbk‘)) #subprocess使用当前系统默认编码,得到结果为bytes类型,在windows下需要用gbk解码
一 日志级别:
CRITICAL = 50 #FATAL=CRITICAL
ERROR = 40
WARNING = 30 #WARN = WARNING
INFO = 20
BEBUG = 10
NOTSET = 0 #不设置
二 默认级别为 warning,默认打印到终端
import logging
logging.debug(‘调试debug‘)
logging.info(‘消息info‘)
logging.warning(‘警告warn‘)
logging.error(‘错误error‘)
logging.critical(‘严重critical‘)
三 为logging指定全局配置,针对所有logger有效,控制打印到文件中
可在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参数会被忽略。 #格式 %(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:用户输出的消息
======介绍=====
可在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用户输出的消息
=====使用=====
import logging logging.basicConfig(filename=‘access.log‘, format=‘%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s‘, datefmt=‘%Y-%m-%d %H:%M:%S %p‘, level=10) logging.debug(‘调试debug‘) logging.info(‘消息info‘) logging.warning(‘警告warn‘) logging.error(‘错误error‘) logging.critical(‘严重critical‘)
=====结果=====
access.log内容: 2017-07-28 20:32:17 PM - root - DEBUG -test: 调试debug 2017-07-28 20:32:17 PM - root - INFO -test: 消息info 2017-07-28 20:32:17 PM - root - WARNING -test: 警告warn 2017-07-28 20:32:17 PM - root - ERROR -test: 错误error 2017-07-28 20:32:17 PM - root - CRITICAL -test: 严重critical part2: 可以为logging模块指定模块级的配置,即所有logger的配置
四 logger模块的Formatter,Handler,Logger,Filter
logger是第一级过滤,然后才能到handler,我们可以给logger和handler同时设置level,但是需要注意的是
Logger is also the first to filter the message based on a level — if you set the logger to INFO, and all handlers to DEBUG, you still won‘t receive DEBUG messages on handlers — they‘ll be rejected by the logger itself. If you set logger to DEBUG, but all handlers to INFO, you won‘t receive any DEBUG messages either — because while the logger says "ok, process this", the handlers reject it (DEBUG < INFO). #验证 import logging form=logging.Formatter(‘%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s‘, datefmt=‘%Y-%m-%d %H:%M:%S %p‘,) ch=logging.StreamHandler() ch.setFormatter(form) # ch.setLevel(10) ch.setLevel(20) l1=logging.getLogger(‘root‘) # l1.setLevel(20) l1.setLevel(10) l1.addHandler(ch) l1.debug(‘l1 debug‘)
五 logger 的配置文件
""" logging配置 """ import os 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‘ 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) # 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)传递 }, }, } 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()
一. 使用
""" MyLogging Test """ import time import logging import my_logging # 导入自定义的logging配置 logger = logging.getLogger(__name__) # 生成logger实例 def demo(): logger.debug("start range... time:{}".format(time.time())) logger.info("中文测试开始。。。") for i in range(10): logger.debug("i:{}".format(i)) time.sleep(0.2) else: logger.debug("over range... time:{}".format(time.time())) logger.info("中文测试结束。。。") if __name__ == "__main__": my_logging.load_my_logging_cfg() # 在你程序文件的入口加载自定义logging配置 demo()
二. !!!关于如何难道logger对象的详细解释!!!
注意注意注意: #1、有了上述方式我们的好处是:所有与logging模块有关的配置都写到字典中就可以了,更加清晰,方便管理 #2、我们需要解决的问题是: 1、从字典加载配置:logging.config.dictConfig(settings.LOGGING_DIC) 2、拿到logger对象来产生日志 logger对象都是配置到字典的loggers 键对应的子字典中的 按照我们对logging模块的理解,要想获取某个东西都是通过名字,也就是key来获取的 于是我们要获取不同的logger对象就是 logger=logging.getLogger(‘loggers子字典的key名‘) 但问题是:如果我们想要不同logger名的logger对象都共用一段配置,那么肯定不能在loggers子字典中定义n个key ‘loggers‘: { ‘l1‘: { ‘handlers‘: [‘default‘, ‘console‘], # ‘level‘: ‘DEBUG‘, ‘propagate‘: True, # 向上(更高level的logger)传递 }, ‘l2: { ‘handlers‘: [‘default‘, ‘console‘ ], ‘level‘: ‘DEBUG‘, ‘propagate‘: False, # 向上(更高level的logger)传递 }, ‘l3‘: { ‘handlers‘: [‘default‘, ‘console‘], # ‘level‘: ‘DEBUG‘, ‘propagate‘: True, # 向上(更高level的logger)传递 }, } #我们的解决方式是,定义一个空的key ‘loggers‘: { ‘‘: { ‘handlers‘: [‘default‘, ‘console‘], ‘level‘: ‘DEBUG‘, ‘propagate‘: True, }, } 这样我们再取logger对象时 logging.getLogger(__name__),不同的文件__name__不同,这保证了打印日志时标识信息不同,但是拿着该名字去loggers里找key名时却发现找不到,于是默认使用key=‘‘的配置
三. django的配置,了解一下即可,跟上面的一样
#logging_config.py LOGGING = { ‘version‘: 1, ‘disable_existing_loggers‘: False, ‘formatters‘: { ‘standard‘: { ‘format‘: ‘[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]‘ ‘[%(levelname)s][%(message)s]‘ }, ‘simple‘: { ‘format‘: ‘[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s‘ }, ‘collect‘: { ‘format‘: ‘%(message)s‘ } }, ‘filters‘: { ‘require_debug_true‘: { ‘()‘: ‘django.utils.log.RequireDebugTrue‘, }, }, ‘handlers‘: { #打印到终端的日志 ‘console‘: { ‘level‘: ‘DEBUG‘, ‘filters‘: [‘require_debug_true‘], ‘class‘: ‘logging.StreamHandler‘, ‘formatter‘: ‘simple‘ }, #打印到文件的日志,收集info及以上的日志 ‘default‘: { ‘level‘: ‘INFO‘, ‘class‘: ‘logging.handlers.RotatingFileHandler‘, # 保存到文件,自动切 ‘filename‘: os.path.join(BASE_LOG_DIR, "xxx_info.log"), # 日志文件 ‘maxBytes‘: 1024 * 1024 * 5, # 日志大小 5M ‘backupCount‘: 3, ‘formatter‘: ‘standard‘, ‘encoding‘: ‘utf-8‘, }, #打印到文件的日志:收集错误及以上的日志 ‘error‘: { ‘level‘: ‘ERROR‘, ‘class‘: ‘logging.handlers.RotatingFileHandler‘, # 保存到文件,自动切 ‘filename‘: os.path.join(BASE_LOG_DIR, "xxx_err.log"), # 日志文件 ‘maxBytes‘: 1024 * 1024 * 5, # 日志大小 5M ‘backupCount‘: 5, ‘formatter‘: ‘standard‘, ‘encoding‘: ‘utf-8‘, }, #打印到文件的日志 ‘collect‘: { ‘level‘: ‘INFO‘, ‘class‘: ‘logging.handlers.RotatingFileHandler‘, # 保存到文件,自动切 ‘filename‘: os.path.join(BASE_LOG_DIR, "xxx_collect.log"), ‘maxBytes‘: 1024 * 1024 * 5, # 日志大小 5M ‘backupCount‘: 5, ‘formatter‘: ‘collect‘, ‘encoding‘: "utf-8" } }, ‘loggers‘: { #logging.getLogger(__name__)拿到的logger配置 ‘‘: { ‘handlers‘: [‘default‘, ‘console‘, ‘error‘], ‘level‘: ‘DEBUG‘, ‘propagate‘: True, }, #logging.getLogger(‘collect‘)拿到的logger配置 ‘collect‘: { ‘handlers‘: [‘console‘, ‘collect‘], ‘level‘: ‘INFO‘, } }, } # ----------- # 用法:拿到俩个logger logger = logging.getLogger(__name__) #线上正常的日志 collect_logger = logging.getLogger("collect") #领导说,需要为领导们单独定制领导们看的日志
十三 re 模块
正则就是用一些具有特殊含义的符号组合到一起(成为正则表达式)来描述字符或者字符串的方法。或者说正则就是用来描述一类事物的规则。常用的正则表达式匹配如下图:
标签:lod 概念 dom wap 权限 SHA256 IV 传参 形式
原文地址:https://www.cnblogs.com/songyongqiang/p/9067511.html