模块
time &datetime模块
import time # print(time.clock()) #返回处理器时间,3.3开始已废弃 , 改成了time.process_time()测量处理器运算时间,不包括sleep时间,不稳定,mac上测不出来 # print(time.altzone) #返回与utc时间的时间差,以秒计算\ # print(time.asctime()) #返回时间格式"Fri Aug 19 11:14:16 2016", # print(time.localtime()) #返回本地时间 的struct time对象格式 # print(time.gmtime(time.time()-800000)) #返回utc时间的struc时间对象格式 # print(time.asctime(time.localtime())) #返回时间格式"Fri Aug 19 11:14:16 2016", #print(time.ctime()) #返回Fri Aug 19 12:38:29 2016 格式, 同上 # 日期字符串 转成 时间戳 # string_2_struct = time.strptime("2016/05/22","%Y/%m/%d") #将 日期字符串 转成 struct时间对象格式 # print(string_2_struct) # # # struct_2_stamp = time.mktime(string_2_struct) #将struct时间对象转成时间戳 # print(struct_2_stamp) #将时间戳转为字符串格式 # print(time.gmtime(time.time()-86640)) #将utc时间戳转换成struct_time格式 # print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将utc struct_time格式转成指定的字符串格式 #时间加减 import datetime # print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925 #print(datetime.date.fromtimestamp(time.time()) ) # 时间戳直接转成日期格式 2016-08-19 # 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分 # # c_time = datetime.datetime.now() # print(c_time.replace(minute=3,hour=2)) #时间替换
实例
import time string_2_struct = time.strptime("13/Mar/2017:11:20:31","%d/%b/%Y:%H:%M:%S") #将 日期字符串 转成 struct时间对象格式 print(time.strftime('%Y-%m-%d %H:%M:%S',string_2_struct)) #将struct时间对象转换成日期字符串
以上代码运行结果
2017-03-13 11:20:31
random模块
import random,string print(random.random()) print(random.randint(1,5)) print(random.randrange(1,5)) print("".join(random.sample('abcdef',2)))
以上代码运行结果:
0.030792454488319798
5
2
fa
生成随机4位数
方法一
import random,string str_source=string.ascii_letters+string.digits print("".join(random.sample(str_source,4)))
方法二
import random,string import random checkcode = '' for i in range(4): current = random.randrange(0,4) if current != i: temp = chr(random.randint(65,90)) else: temp = random.randint(0,9) checkcode += str(temp) print (checkcode)
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 输出用于分割文件路径的字符串 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所指向的文件或者目录的最后修改时间
shelve模块
import shelve d= shelve.open('shelve_test') def stu_data(name,age): print("register stu",name,age) name = ["alex","rain","test"] info ={"name":"alex","age":22} d['test']=name d["info"]=info d["func"]=stu_data
d.close()
以上代码会产生三个文件:shelve_test.bak;shelve_test.dat;shelve_test.dir
读取产生的三个文件
def stu_data(name,age): print("register stu",name,age) d= shelve.open('shelve_test') print(d.get("test")) print(d.get("info")) d["func"]("test",30) d.close
以上代码运行结果
['alex', 'rain', 'test'] {'name': 'alex', 'age': 22} register stu test 30
shutil模块
shutil.copyfileobj
将test.txt文件内容拷贝到另一个文件test.txt中,可以部分内容
import shutil f1=open("test.txt") f2=open("test_new.txt","w") shutil.copyfileobj(f1,f2)
将D:\360.7z拷贝到D:\test.7z
import shutil shutil.copyfile(r"D:\360.7z",r"D:\test.7z")
shutil.copy2
拷贝文件和状态信息
将D:\360.7z拷贝到D:\test.7z
import shutil shutil.copy2(r"D:\360.7z",r"D:\test.7z")
shutil.make_archive
将C:\Downloads\Tencent\QQ下的内容打包到D:\test2.tar.gz
import shutil ret=shutil.make_archive(r"d:\test2","gztar",root_dir=r"C:\Downloads\Tencent\QQ")
tarfile模块
C:\QMDownload\SoftMgr里面的内容装在zhou这个文件夹下打包到E:\test1.tar
import tarfile tar = tarfile.open(r"E:\test1.tar",'w') tar.add(r"C:\QMDownload\SoftMgr",arcname="zhou") tar.close()
C:\QMDownload\SoftMgr里面的内容装在QMDownload\SoftMgr这个文件夹打包到E:\test2.tar
import tarfile tar = tarfile.open(r"E:\test2.tar",'w') tar.add(r"C:\QMDownload\SoftMgr") tar.close()
xml处理模块
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>
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作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) for i in child: print(i.tag,i.text) #只遍历year 节点 for node in root.iter('year'): print(node.tag,node.tex
修改和删除xml文档内容
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") tree.write("xmltest.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) #打印生成的格式
ConfigParser模块
用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser。
来看一个好多软件的常见文档格式如下
[DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port = 50022 ForwardX11 = no
如果想用python生成一个这样的文档怎么做呢?
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)
读生成的文档里的内容
import configparser config= configparser.ConfigParser() print(config.sections()) config.read("example.ini") print(config.sections()) section_name=config.sections()[1] print(config[section_name]["host port"]) for i,v in config[section_name].items(): print(i,v)
以上代码运行结果
[] ['bitbucket.org', 'topsecret.server.com'] 50022 host port 50022 forwardx11 no compressionlevel 9 compression yes serveraliveinterval 45
configparser增删改查语法
[section1] k1 = v1 k2:v2 [section2] k1 = v1 import ConfigParser config = ConfigParser.ConfigParser() config.read('i.cfg') # ########## 读 ########## #secs = config.sections() #print secs #options = config.options('group2') #print options #item_list = config.items('group2') #print item_list #val = config.get('group1','key') #val = config.getint('group1','key') # ########## 改写 ########## #sec = config.remove_section('group1') #config.write(open('i.cfg', "w")) #sec = config.has_section('wupeiqi') #sec = config.add_section('wupeiqi') #config.write(open('i.cfg', "w")) #config.set('group2','k1',11111) #config.write(open('i.cfg', "w")) #config.remove_option('group2','age') #config.write(open('i.cfg', "w"))
hashlib模块
实例:
import hashlib # md5加密是不能反解的,但是可以撞库 m=hashlib.md5() # 创建一个md5对象
m.update(b"alex") # 加密字符串'alex' print(m.hexdigest()) # 显示加密后的随机字符串 m.update(b"li") #"alex"追加一个"li" 组成"alexli" print(m.hexdigest()) #打印出来的效果和直接hashlib"alexli"一样 m2=hashlib.md5() m2.update(b"alexli") print(m2.hexdigest())
以上代码运行结果
534b44a19bf18d20b71ecc4eb77c572f
5f48164ebf9ea14d675ff31bce71c7da
5f48164ebf9ea14d675ff31bce71c7da
用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
######## sha1 ######## hash = hashlib.sha1() hash.update(bytes('admin', encoding='utf-8')) print(hash.hexdigest()) # ######## sha256 ######## hash = hashlib.sha256() hash.update(bytes('admin', encoding='utf-8')) print(hash.hexdigest()) # ######## sha384 ######## hash = hashlib.sha384() hash.update(bytes('admin', encoding='utf-8')) print(hash.hexdigest()) # ######## sha512 ######## hash = hashlib.sha512() hash.update(bytes('admin', encoding='utf-8')) print(hash.hexdigest())
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。
import hashlib # ######## md5 ######## hash = hashlib.md5(bytes('898oaFs09f',encoding="utf-8")) hash.update(bytes('admin',encoding="utf-8")) print(hash.hexdigest())
python内置还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密
import hmac h = hmac.new(bytes('898oaFs09f',encoding="utf-8")) h.update(bytes('admin',encoding="utf-8")) print(h.hexdigest())
hmac模块
import hmac h_obj=hmac.new(b"salt",b"hello") print(h_obj.hexdigest())
以上代码运行结果
3a2484b4f0df4f4157d069598a334b31
logging模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug()
, info()
, warning()
, error()
and critical() 5个级别。
日志格式
%(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="app.log", level=logging.WARNING, format='%(asctime)s %(process)d %(filename)s:%(lineno)d %(funcName)s - %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') logging.debug("test debug") logging.info("test info ") logging.warning("user [alex] attempted wrong password more than 3 times") logging.error("testerror ") logging.critical("server is down") def app_run(): logging.warning("app has been run too long...") app_run()
以上代码产生一个app.log文件,app.log文件内容为:
11/16/2016 02:17:08 PM 4684 logging mod.py:10 <module> - WARNING: user [alex] attempted wrong password more than 3 times 11/16/2016 02:17:08 PM 4684 logging mod.py:11 <module> - ERROR: testerror 11/16/2016 02:17:08 PM 4684 logging mod.py:12 <module> - CRITICAL: server is down 11/16/2016 02:17:08 PM 4684 logging mod.py:16 app_run - WARNING: app has been run too long...
logger多输出
import logging # create logger 'TEST-LOG'是自己可以起的名字 logger = logging.getLogger('TEST-LOG') logger.setLevel(logging.DEBUG) # create console handler and set level to debug ch = logging.StreamHandler() #屏幕输出 ch.setLevel(logging.WARNING) # # # create file handler and set level to warning fh = logging.FileHandler("access.log",encoding="utf-8") #文件输出 fh.setLevel(logging.ERROR) fh_formatter = logging.Formatter('%(asctime)s %(process)d %(filename)s:%(lineno)d - %(levelname)s: %(message)s') ch_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(fh_formatter) ch.setFormatter(ch_formatter) logger.addHandler(fh) logger.addHandler(ch) logger.warning("warning commint...") logger.error("error happend..")
以上代码会产生屏幕输出及access.log文件输出
屏幕内容为
2016-11-16 16:41:10,766 - TEST-LOG - WARNING - warning commint...
2016-11-16 16:41:10,766 - TEST-LOG - ERROR - error happend..
access.log文件内容为
2016-11-16 16:41:10,766 10616 logger_多输出.py:24 - ERROR: error happend..
logger文件分割
import logging from logging import handlers logger = logging.getLogger(__name__) log_file = "timelog.log" # fh = handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3,encoding='utf-8') fh = handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3,encoding='utf-8') #when="S"指定时间为秒,interval=5指定间隔为5,backupCount=3指定最多分割多少份。 formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s') fh.setFormatter(formatter) logger.addHandler(fh) logger.warning("test1") logger.warning("test12") logger.warning("test13") logger.warning("test14")
re模块
常用正则表达式符号
'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以 '*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a'] '+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb'] '?' 匹配前一个字符1次或0次 '{m}' 匹配前一个字符m次 '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb'] '|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC' '(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的 '\Z' 匹配字符结尾,同$ '\d' 匹配数字0-9 '\D' 匹配非数字 '\w' 匹配[A-Za-z0-9] '\W' 匹配非[A-Za-z0-9] 's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t' '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}
最常用的匹配语法
re.match 从string的开始位置匹配,只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none
re.search 扫描整个string,返回第一个匹配到的值,匹配不成功返回none
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.split 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换
反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
仅需轻轻知道的几个匹配模式
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同) M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图) S(DOTALL): 点任意匹配模式,改变'.'的行为
序列化
Python中用于序列化的两个模块
- json 用于【字符串】和 【python基本数据类型】 间进行转换
- pickle 用于【python特有的类型】 和 【python基本数据类型】间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
实例一:
import pickle data = {'k1':123,'k2':'hello'} #pickle.dumps 将数据通过特殊的形式转换为只有python语言认识的字符串 p_str = pickle.dumps(data) print(p_str) # 反序列化 data = pickle.loads(p_str) print(data)
实例二:
import pickle data = {'k1':123,'k2':'hello'} #pickle.load 将数据通过特殊的形式转换为只有python语言认识的字符串,并写入文件 with open('./result.pk','wb') as f: pickle.dump(data,f) #反序列化 with open('./result.pk','rb') as f: ret = pickle.load(f) print(ret)
实例三:
import json data = {'k1':123,'k2':'hello'} #json.dumps 将数据通过特殊的形式转换为所有程序都能认识的字符串 j_str = json.dumps(data) print(j_str,type(j_str)) # 反序列化 ret = json.loads(j_str) print(ret,type(ret))
实例四:
import json data = {'k1':123,'k2':'hello'} #json.dump 将数据通过特殊的形式转换为所有程序都认识的字符串,并写入文件 with open('./result.js','w') as f: json.dump(data,f) #反序列化 with open('./result.js','r') as f: ret = json.load(f) print(ret)