python自动化开发-[第六天]-常用模块、面向对象
今日概要:
1、常用模块
- os模块
- random模块
- shutil模块
- hashlib模块
- pickle/json模块
- shelve模块
- configparser模块
- subprocess模块
- xml模块
- logging模块
- sys模块
- re模块
- time模块
- importlib模块
-base64模块
2、软件开发规范
3、初识面向对象
一、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.listdir('.') import os print(os.path.abspath('a/b/c.txt')) #查看文件的绝对路径 print(os.path.abspath('/a/b/c.txt')) #E:\a\b\c.txt print(os.path.split('E:\\a\\c.txt')) print(os.path.dirname('E:\\a\\c.txt')) print(os.path.dirname('E:\\a')) print(os.path.basename('E:\\a\\a,txt')) print(os.path.exists('E:\\a')) print(os.path.exists(r'C:\Users\liujiliang\PycharmProjects\py_day_01\dragon\day06')) print(os.path.isabs('E:\\day06')) print(os.path.isabs('day06')) print(os.path.getsize(r'C:\Users\liujiliang\PycharmProjects\py_day_01\dragon\day06\test.py')) #找到第一个绝对路径往后拼接,如果没有继续往后拼接,否则直接返回 print(os.path.join('a','E:\\b','c.txt')) print(os.path.join('a','/b','c.txt')) #/b/c.txt #只在windows里有效,把上一级的..变成上一级目录 print(os.path.normcase('c:/wIndows\\system32\\') ) print(os.path.normpath('c://windows\\System32\\../Temp/'))
返回上一级目录示例:
import os,sys #__file__取当前文件 print(os.path.abspath(__file__)) BASE_DIR=os.path.dirname(os.path.dirname(__file__)) BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) #E:/goto/s17/day06/bbb/spam.py/../.. BASE_DIR=os.path.normpath(os.path.join(__file__, os.pardir, os.pardir) ) print(BASE_DIR)
二、random模块
随机选取ip
import random proxy_ip=[ '1.1.1.1', '1.1.1.2', '1.1.1.3', '1.1.1.4', ] print(random.choice(proxy_ip))
取列表里任意两个元素组合示例:
import random print(random.sample([1,'23',[4,5]],2))
乱序组合示例:
import random item=[1,3,5,7,9] random.shuffle(item) print(item)
随机验证码示例:
def v_code(n=5): res='' for i in range(n): num=random.randint(0,9) s=chr(random.randint(65,90)) add=random.choice([num,s]) res+=str(add) return res print(v_code(6)) #输出结果 76R7B3
三、shutil模块
1、shutil.copyfileobj(fsrc, fdst[, length])
将文件内容copy到另外一个文件
import shutil shutil.copyfileobj(open('test.py','r'),open('test1.py','w'))
2、shutil.copyfile(src, dst)
copy文件,目标文件不需要存在
shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在
3、shutil.copymode(src, dst)
仅copy权限,内容、用户、组全都不变
shutil.copymode('f1.log', 'f2.log') #目标文件必须存在
4、shutil.copystat(src, dst)
仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copystat('f1.log', 'f2.log') #目标文件必须存在
5、shutil.copytree(src, dst, symlinks=False, ignore=None) shutil.ignore_patterns(*patterns)
递归去copy文件
import shutil shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
copy软连接
import shutil shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) ''' 通常的拷贝都把软连接拷贝成硬链接,即对待软连接来说,创建新的文件 '''
6、shutil.move(src, dst)
递归的去移动文件,它类似mv命令,其实就是重命名。
import shutil shutil.move('folder1', 'folder3')
7、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 两个模块来进行的
tarfile示例:
#解压 import tarfile t=tarfile.open('data_bak.tar.gz','r') t.extractall('extract_dir') t.close() #压缩 import tarfile t=tarfile.open('egon1.tar','w') t.add(r'E:\wupeiqi\s17\day06\bbb\b.py',arcname='a.bak') t.add(r'E:\wupeiqi\s17\day06\bbb\spam.py',arcname='b.bak') t.close() t=tarfile.open('egon1.tar','r') t.extractall('extract_dir2')
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()
四、hashlib模块
MD5 算法
三个特点:
1.内容相同则hash运算结果相同,内容稍微改变则hash值则变
2.不可逆推
3.相同算法:无论校验多长的数据,得到的哈希值长度固定。
m = hashlib.md5() #生成一个对象 #python3默认是unicode,需要进行encode m.update('1311323213哈哈'.encode('utf-8')) print (m.hexdigest())
读一个10G的文件,md5校验方法
m = hashlib.md5() with open(r'/home/alex','rb') as f : for line in f : m.update(line) md5_num = m.hexdigest()
密码加严
#hmac版本 import hmac h = hmac.new('123123'.encode('utf-8')) h.update('helloword'.encode('utf-8')) print (h.hexdigest()) #hashlib版本 import hashlib m = hashlib.md5('123123'.encode('utf-8')) m.update('123'.encode('utf-8')) print (m.hexdigest())
模拟撞库
import hashlib passwds=[ 'alex3714', 'alex1313', 'alex94139413', 'alex123456', '123456alex', 'a123lex', ] def make_passwd_dic(passwds): dic={} for passwd in passwds: m=hashlib.md5() m.update(passwd.encode('utf-8')) dic[passwd]=m.hexdigest() return dic def break_code(cryptograph,passwd_dic): for k,v in passwd_dic.items(): if v == cryptograph: print('密码是===>\033[46m%s\033[0m' %k) cryptograph='aee949757a2e698417463d47acac93df' break_code(cryptograph,make_passwd_dic(passwds)) 模拟撞库破解密码
五、pickle/json模块
1、什么是序列化?
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等
2、JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
3、json的使用流程
#!/usr/bin/python # -*- coding:utf-8 -*- import json dic = { 'name':'alex', 'age':10, 'o':'iii' } #序列化 res = json.dumps(dic) with open('a.json','w') as f: f.write(res) #反序列化 with open('a.json','r') as f: res = json.loads(f.read()) print (res,type(res)) #简单方式 #序列化 json.dump(dic,open('b.json','w')) #反序列化 res = json.load(open('b.json','r')) print (res,type(res))
4、json的loads和load的区别
loads针对内存对象,即将Python内置数据序列化为字串
load针对文件句柄
5、json和pickle支持的数据类型:
json:json 只支持,str,float.set,dict,list,tuple
pickle:支持任何数据类型的序列化
pickle示例:
accout = { 'id':123, 'credit':15000, 'balance':8000, 'expire_date':'2020-5-21', 'password':'321' } import pickle with open('account.json','wb') as f : f.write(pickle.dumps(accout)) f.close() #等价于 pickle.dump(accout,f) accout = pickle.load(f) == pickle.load(f.read())
六、shelve模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
import shelve f=shelve.open(r'sheve.txt') f['stu1_info']={'name':'egon','age':18,'hobby':['piao','smoking','drinking']} # f['stu2_info']={'name':'gangdan','age':53} # f['school_info']={'website':'http://www.pypy.org','city':'beijing'} print(f['stu1_info']['hobby']) f.close()
七、configparser模块
***configparser 默认输出文件都为小写,可以用过类的继承,修改其属性
示例代码如下:
import ConfigParser class myconf(ConfigParser.ConfigParser): def __init__(self,defaults=None): ConfigParser.ConfigParser.__init__(self,defaults=None) def optionxform(self, optionstr): return optionstr
1、配置文件如下:
# 注释1 ; 注释2 [section1] k1 = v1 k2:v2 user=egon age=18 is_admin=true salary=31 [section2] k1 = v1
读取:
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') #删除整个标题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'))
添加一个ini文档:
import configparser config = configparser.ConfigParser() config["DEFAULT"] = {'ServerAliveInterval': '45', 'Compression': 'yes', 'CompressionLevel': '9'} config['bitbucket.org'] = {} config['bitbucket.org']['User'] = 'hg' config['topsecret.server.com'] = {} topsecret = config['topsecret.server.com'] topsecret['Host Port'] = '50022' # mutates the parser topsecret['ForwardX11'] = 'no' # same here config['DEFAULT']['ForwardX11'] = 'yes' with open('example.ini', 'w') as configfile: config.write(configfile)
经典例子-示例文件:
[DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port = 50022 ForwardX11 = no
1、获取所有节点:
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') res=config.sections() print(res) ''' 打印结果: ['bitbucket.org', 'topsecret.server.com'] '''
2、获取指定节点下所有的键对值
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') res=config.items('bitbucket.org') print(res) ''' 打印结果:(包含DEFAULT以及bitbucket.org这俩标题下所有的items) [('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')] '''
3、获取指定节点下所有的键
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') res=config.options('bitbucket.org') print(res) ''' 打印结果:(包含DEFAULT以及bitbucket.org这俩标题下所有的键) ['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']'''
4、获取指定节点下指定的key值
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') res1=config.get('bitbucket.org','user') res2=config.getint('topsecret.server.com','port') res3=config.getfloat('topsecret.server.com','port') res4=config.getboolean('topsecret.server.com','ForwardX11') print(res1) print(res2) print(res3) print(res4) ''' 打印结果: hg 50022.0 False '''
5、检查、删除、添加节点
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') #检查 has_sec=config.has_section('bitbucket.org') print(has_sec) #打印True #添加节点 config.add_section('egon') #已经存在则报错 config['egon']['username']='gangdan' config['egon']['age']='18' config.write(open('test.ini','w')) #删除节点 config.remove_section('egon') config.write(open('test.ini','w'))
6、检查、删除、设置指定组内的键值对
import configparser config=configparser.ConfigParser() config.read('test.ini',encoding='utf-8') #检查 has_sec=config.has_option('bitbucket.org','user') #bitbucket.org下有一个键user print(has_sec) #打印True #删除 config.remove_option('DEFAULT','forwardx11') config.write(open('test.ini','w')) #设置 config.set('bitbucket.org','user','gangdang') config.write(open('test.ini','w'))
七、subprocess模块
import subprocess res=subprocess.Popen('pwd',shell=True,stdout=subprocess.PIPE) print(res) #默认返回一个对象 print(res.stdout.read().decode('utf-8')) #默认生成的是bytes需要进行decode import subprocess res=subprocess.Popen('dasdasdad',shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) print('=====>',res.stdout.read()) #标准输出 print('=====>',res.stderr.read().decode('utf-8')) #标准错误输出 #ls |grep txt$ 模拟(windows版) res1=subprocess.Popen(r'dir E:\wupeiqi\s17\day06',shell=True,stdout=subprocess.PIPE) # print(res1.stdout.read()) res=subprocess.Popen(r'findstr txt*',shell=True, stdin=res1.stdout, stderr=subprocess.PIPE, stdout=subprocess.PIPE) print('===>',res.stdout.read().decode('gbk'))#管道取一次就空了 print('===>',res.stdout.read().decode('gbk'))
八、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> xml数据
print(root.iter('year')) #全文搜索 print(root.find('country')) #在root的子节点找,只找一个 print(root.findall('country')) #在root的子节点找,找所有
xml用法:
import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() print(root.tag) #遍历xml文档 for child in root: print('========>',child.tag,child.attrib,child.attrib['name']) for i in child: print(i.tag,i.attrib,i.text) #只遍历year 节点 for node in root.iter('year'): print(node.tag,node.text) #--------------------------------------- import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() #修改 for node in root.iter('year'): new_year=int(node.text)+1 node.text=str(new_year) node.set('updated','yes') node.set('version','1.0') tree.write('test.xml') #删除node for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml')
自己创建xml文档
import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) age = ET.SubElement(name,"age",attrib={"checked":"no"}) sex = ET.SubElement(name,"sex") sex.text = '33' name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) age = ET.SubElement(name2,"age") age.text = '19' et = ET.ElementTree(new_xml) #生成文档对象 et.write("test.xml", encoding="utf-8",xml_declaration=True) ET.dump(new_xml) #打印生成的格式
九、logging模块
1、第一种方法生成日志:
import logging ''' 一:如果不指定filename,则默认打印到终端 二:指定日志级别: 指定方式: 1:level=10 2:level=logging.ERROR 日志级别种类: CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 三:指定日志级别为ERROR,则只有ERROR及其以上级别的日志会被打印 ''' 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('warning') logging.error('error') logging.critical('critical') logging.log(10,'log') #如果level=40,则只有logging.critical和loggin.error的日志会被打印
2、第二种以对象形式生成日志
#create logger 定义全局 logger = logging.getLogger('TEST-log') logger.setLevel(logging.DEBUG) #create console handle and set level to debug ch = logging.StreamHandler() ch.setLevel(logging.INFO) #create file handle and set level to debug # fh = logging.FileHandler('access.log') # fh.setLevel(logging.WARNING) #设置轮滚,按时间轮滚 #fh = handlers.TimedRotatingFileHandler('access.log',when="S",interval=5,backupCount=3) #设置轮滚按大小轮滚 fh = handlers.RotatingFileHandler("access.log",maxBytes=4,backupCount=2) fh.setLevel(logging.WARNING) #formatter formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') #add formatter to ch and fh ch.setFormatter(formatter) fh.setFormatter(formatter) logger.addHandler(fh) logger.addHandler(ch) #application code logger.debug('debug message') logger.info('info message') logger.warning('warning message') logger.critical('critical message') logger.error('error message') #全局的优先级最高 ,其次才是局部优先级
3、可在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用户输出的消息
十、sys模块
sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sys.maxint 最大的Int值 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称
示例进度条:
#\r回行首,覆盖式输出 for i in range(50): sys.stdout.write('%s\r' %('#'*i)) sys.stdout.flush() time.sleep(0.1) ''' 在pycharm里执行无效 '''
十一、time模块
时间模块整体转换图
#!/usr/bin/python # -*- coding:utf-8 -*- import time import datetime #timezone,时区 print (time.timezone/60/60) #asctime,返回英文格式时间 print (time.asctime()) #时间对象 print (time.localtime()) a = time.localtime() print (a.tm_year,a.tm_mon) #格林威治时间 print (time.gmtime()) #自定义时间 strftime print (time.strftime("%Y-%m")) #把时间按到指定格式转换 stuck_time = time.localtime(time.time() - 86400) print (time.strftime("%Y-%m-%d %H:%M:%S",stuck_time)) #自定义时间-时间戳转换 a = time.strptime('2017-02-17','%Y-%m-%d') print (a) #时间对象 print (time.mktime(a)) #时间戳 #时间戳到 自定义转换, time.gmtime(1487260800.0) print (time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime(1487260800.0))) #时间加减 print (datetime.datetime.now()) print(datetime.datetime.fromtimestamp(time.time())) print (datetime.datetime.now() - datetime.timedelta(3)) print (datetime.datetime.now() - datetime.timedelta(hours=3)) print (datetime.datetime.now() - datetime.timedelta(hours=-3)) #时间的替换 replace print (datetime.datetime.now().replace(minute=3,hour=2))
十二、re正则模块
#re.search,匹配返回值 print(re.search('e','alex make love')) print(re.search('^e','alex make love')) print(re.search('e','alex make love')) #匹配以e开头的 print(re.match('e','alex make love')) print(re.match('a','alex make love').group()) #group分组,group()显示所有匹配值,group(1) 显示第一个组匹配的值,和group()和findall的?:一个功能 print(re.search('al(e)x\smak(e)','alex make love').group()) print(re.findall('al(?:e)x\smak(?:e)','alex make love')) print(re.split('[ab]','abcd')) #先以a进行分割,在以b进行分割 print(re.sub('^a','A','alex make love')) print(re.sub('a','A','alex make love')) #分组替换 print (re.sub('^(\w+)(\s)(\w+)(\s)(\w+)$',r'\5\4\3\2\1','alex make love')) print (re.sub('^(\w+)(\W+)(\w+)(\W+)(\w+)$',r'\5\4\3\2\1','alex make love')) print (re.sub('^(\w+)(\W+)(\w+)(\W+)(\w+)$',r'\5\4\3\2\1','alex " \ + = make ----/== love')) #匹配整数 print (re.findall(r'\-?\d+\.\d+|(\-?\d+)','1-2*((60-30+(-40.0/5)*(9-2*5.33/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))')) #或者,左面执行成功,右面不会执行,一个条件成功就终止 print(re.search('companies|company','my company is already done,all companies
importlib模块
当配置文件里出现,一堆字符串的类,绝大部分都是通过importlib和反射getattr实现调用
import importlib st = 'src.pulgin.disk.Disk' module_path,cls_name = st.rsplit('.',maxsplit=1) #切分路径 module = importlib.import_module(module_path) #将字符串以模块形式导入 cls = getattr(module,cls_name) #通过反射,获取类 obj = cls() #实例化对象
base64模块
import base64 # a = '[上线申请]标准dspserver直接写kafka&ileaf优化参数避免被在线误修改' a = '[上线申请]标准dspserver直接写kafka&ileaf优化参数避免被在线误修改asdadasddasdddddddddddddddddddddddddddddddddddddd' b = bytes(a,encoding="utf-8") s = base64.b64encode(b) print(str(s)) """ W+S4iue6v+eUs+ivt13moIflh4Zkc3BzZXJ2ZXLnm7TmjqXlhplrYWZrYSZpbGVhZuS8mOWMluWPguaVsOmBv+WFjeiiq+WcqOe6v+ivr+S/ruaUuWFzZGFkYXNkZGFzZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQ= """
十三、软件开发规范
为什么要设计好目录结构?
1.可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。
2.可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。
二、目录组织方式
示例:
ATM/
|-- bin/
| |-- __init__
| |-- start.py
|
|-- core/
| |-- tests/
| | |-- __init__.py
| | |-- test.main.py
| |
| |-- __init__.py
| |-- test_main.py|
|
|-- conf/
| |-- __init__.py
| |-- setting.py
|
|---db/
| |--db.json
|
|-- docs/
|
|-- lib/
| |-- __init__.py
| |-- common.py
|
|-- log/
| |-- access.log
|
|-- __init__.py
|-- README
bin/
: 存放项目的一些可执行文件,当然你可以起名script/
之类的也行,但bin/更直观。易懂core/
: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。 (2) 其子目录tests/
存放单元测试代码; (3) 程序的入口最好命名为main.py
。- conf/:配置文件。
- db/:数据库文件。
- lib/:库文件,放自定义模块和包。
docs/
: 存放一些文档。- log/: 日志文件。
README
: 项目说明文件
十四、初识面向对象
1、对象就是特征和技能的结合体(变量和函数的结合体)
2、面向对象的优缺点
优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方
3、什么是类?
在python中,用变量表示特征,用函数表示技能,因而类是变量与函数的结合体,对象是变量与方法(指向类的函数)的结合体
4、类的语法定义:
class Foo: '''文档注释''' pass
5、类的使用
#!/usr/bin/python # -*- coding:utf-8 -*- # class Foo: # '''文档注释''' # pass #类是一系列对象共有的特征(变量的定义)与技能(函数的定义)的结合体 class Chinese: country='China' # Chinese.__init__(p1,'egon','18','male') def __init__(self,name,age,sex): #p1.Name=name;p1.Age=age,p1.Sex=sex self.Name=name self.Age=age self.Sex=sex def talk(self): print('talking',self) #属性的引用 print(Chinese.country) print(Chinese.talk) Chinese.talk(123) Chinese.x=1 print(Chinese.x) Chinese.country=123123123123123 print(Chinese.country) #实例化 class Chinese: country = 'China' # Chinese.__init__(p1,'egon','18','male') def __init__(self, name, age, sex): # p1.Name=name;p1.Age=age,p1.Sex=sex self.Name = name self.Age = age self.Sex = sex def talk(self): print('%s is talking' %self.Name) # p1=Chinese('egon','18','male') #Chinese.__init__(p1,'egon','18','male') # p2=Chinese('alex','9000','female') #Chinese.__init__(p1,'egon','18','male') #对象的使用:只有一种,就是属性引用 print(p1.Name) print(p1.Age) print(p1.Sex) print(p2.Name) print(p1.country) print(p2.country) p1.talk() p2.talk() country = 'aaaaaaaaaa' class Chinese: country = 'China' def __init__(self, name, age, sex): # self.country=123123123123123123 self.Name = name self.Age = age self.Sex = sex def talk(self): print('%s is talking' %self.Name) #类名称空间 # print(Chinese.__dict__) #对象的空间 p1=Chinese('egon','18','male') #Chinese.__init__(p1,'egon','18','male') p2=Chinese('alex','180','male') # 先去对象的__dict__里去找,在去类里去找,找不到返回错误 # print(p1.__dict__) # print(p1.Age) #p1.__dict__['Age'] # print(p1.country,id(p1.country)) # print(p2.country,id(p2.country))
# 绑定方法和函数的区别,函数会传入对应的参数,绑定方法会把自己传入到函数里 # print(Chinese.talk) # print(p1.talk) # p1.talk() #Chines.talk(p1) # print(p2.talk) # p2.talk()#chinese.talk(p2) print(type(p1))