1、time模块(※※※※)
import time #导入时间模块 print(time.time()) #返回当前时间的时间戳,可用于计算程序运行时间 print(time.localtime()) #返回当地时间的结构化时间格式,参数默认为时间戳 print(time.gmtime) #返回UTC时间的结构化时间格式 print(time.mktime(time.localtime())) #将结构化时间转换为时间戳 print(time.strftime("%Y-%m-%d %X",time.localtime())) #将结构化时间转换为字符串时间 print(time.strptime("2019:9:30:12:55:36","%Y:%m:%d:%X")) #将字符串时间转换为结构化时间 print(time.asctime()) #将结构化时间或表示时间的元组转换为'Sun Jun 20 23:21:05 1993'的格式 print(time.ctime()) #将时间戳转换为time.asctime格式,默认time.time为参数
PS:由于平时习惯,strftime比较常用,strptime和它是反操作,下列方法输出格式能更符合人们的习惯
import datetime #导入datetime模块 print(datetime.datetime.now()) #输出2019-09-30 15:15:09.562809的格式
2、random模块(※※)
import random print(random.random()) #返回0到1之间的随机浮点数 print(random.randint(1,3)) #返回1到3之间的随机整数,包括3 print(random.randrange(1,3)) #返回1到3之间的随机整数,不包括3 print(random.choice([1,'23',[4,5]])) #随机返回列表中一个数据 print(random.sample([1,'23',[4,5]],2)) #随机返回列表中两个数据 print(random.uniform(1,3)) #返回1到3之间的浮点数 item=[1,3,5,7,9] random.shuffle(item) print(item) #把item列表打乱
3、os模块(※※※※)
import os os.getcwd() #返回当前脚本工作目录路径 os.chdir("dirname") #改变当前脚本工作目录 os.makedirs('dirname1/dirname2') #生成多层递归目录 os.removedirs('dirname1') #若目录为空则删除,并递归到上一级目录,若也为空则继续删除,依此类推 os.mkdir('dirname') #生成单级目录 os.rmdir('dirname') #删除单级空目录,若目录不为空则无法删除并报错 os.listdir('dirname') #以列表方式返回指定目录下的所有文件和子目录,包括隐藏文件 os.remove() #删除一个文件 os.rename("oldname","newname") #重命名文件或目录 os.stat('path/filename') #获取文件或目录 os.linesep #输出当前平台使用的行终止符(win下为"\r\n",Linux下为"\n") os.pathsep #输出用于分割文件路径的字符串(win下为;,Linux下为:) os.path.abspath(path) #返回path规范化的绝对路径 os.path.split(path) #返回path分割成的目录和文件名二元组 os.path.dirname(path) #返回path的目录 os.path.basename(path) #返回path的文件名,若path以/或\结尾则返回空值 os.path.exists(path) #path存在返回True,不存在则返回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指向的文件或者目录最后修改时间
PS:其中os.path.join较为常用。
4、sys模块(※※※)
import sys sys.argv #命令行参数List,第一个元素是程序本身路径 sys.exit(n) #退出程序,正常退出时exit(0) sys.version #获取Python解释程序的版本信息 sys.maxint #最大的Int值 sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform #返回操作系统平台名称
PS:其中sys.argv较为常用,下面代码实现进度条的打印,使用flush刷新屏幕打印
import sys,time for i in range(100): sys.stdout.write('#') time.sleep(1) sys.stdout.flush()
5、json&pickle(※※※※)
import json dic={'name':'alvin','age':23,'sex':'male'} #定义一个字典,为字典格式 f=open('序列化对象','w') j=json.dumps(dic) #把字典序列化,即单引号变双引号,然后再在最外面加单引或双引变成所有编程语言都可用的字符串格式 f.write(j) #也可以用dump用法,这两行则等价于json.dump(dic,f) f.close() f=open('序列化对象') data=json.loads(f.read()) #把字符串反序列化,即把字符串格式变成字典格式,也可以用load用法,这两行则等价于data=json.load(f)
PS:dump和load用法更加简洁,但是仅限于文件操作,所以还是推荐dumps和loads。另外dumps和loads不是一定要连用,只要字符串满足dumps后的格式,就可以直接进行loads操作,dump和load同理。pickle和json用法基本上相同,json是可以在不同语言之间交换数据的,而pickle只在python之间使用。 json只能序列化最基本的数据类型,而pickle可以序列化所有的数据类型,包括类,函数都可以序列化(不常用)
6、shelve模块(※※※)
import shelve def member_info(name, age): print("Member info:", name, age) name = ['Jack', 'Maxwell', 'Tom'] info = {'name': 'Maxwell', 'age': 18} with shelve.open('demo') as data: data['name'] = name #持久化列表 data['info'] = info #持久化字典 data['func'] = member_info
PS:shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写。key必须为字符串,而值可以是python所支持的数据类型
7、xml模块(※※)
xml格式,用<>区别数据结构:
"1.0"?>"Liechtenstein"> "yes">2 2008 141100 "Austria" direction="E"/> "Switzerland" direction="W"/> "Singapore"> "yes">5 2011 59900 "Malaysia" direction="N"/> "Panama"> "yes">69 2011 13600 "Costa Rica" direction="W"/> "Colombia" direction="E"/>
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.text) #----------修改---------- 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) #打印生成的格式
PS:json比xml用起来更简单,但xml出现很早,以至于现在很多系统接口还是xml
8、re模块(※※※※※)
import re ret=re.findall('a..in','helloalvin') #元字符.的用法,一个.表示有一个字符 print(ret) #输出['alvin'],re.findall是在字符串中检索所有的满足格式的子字符串并放在列表里 ret=re.findall('^a...n','alvinhelloawwwn') #元字符^的用法,表示从字符串开头开始匹配 print(ret) #输出['alvin'] ret=re.findall('a...n$','alvinhelloawwwn') #元字符$的用法,表示从字符串结尾开始匹配 print(ret) #输出['awwwn'] ret=re.findall('abc*','abcccc') #元字符*的用法,表示字符c重复多次,也可为0次,会自动匹配最多次,称贪婪匹配 print(ret) #输出['abcccc'] ret=re.findall('abc+','abccc') #元字符+的用法,表示字符c重复多次,最少有1次,会自动匹配最多次 print(ret) #['abccc'] ret=re.findall('abc?','abccc') #元字符?的用法,表示字符c重复0次或1次,会自动匹配1次 print(ret) #输出['abc'] ret=re.findall('abc{1,4}','abccc') #元字符{}的用法,表示字符c重复指定范围次数,会自动匹配最多次 print(ret) #输出['abccc']
PS:上面的元字符*,+,?,{}等都是贪婪匹配,也就是按尽可能多的次数匹配,在后面加?号则可变成惰性匹配
ret=re.findall('abc*?','abcccccc') #惰性匹配字符c为最少次数0次 print(ret) #输出['ab']
ret=re.findall('a[bc]d','acd') #元字符的字符集[]的用法,表示在字符集中选择一个进行匹配 print(ret) #输出['acd'] ret=re.findall('[a-z]','acd') #字符集[]中有功能的符号:-^\,a-z表示从a到z的所有字母 print(ret) #输出['a', 'c', 'd'] ret=re.findall('[.*+]','a.cd+') #除了-^\的其他符号则变成一般字符,不具功能 print(ret) #输出['.', '+'] ret=re.findall('[^ab]','45bdha3') #字符集[]中^表示“非”,^ab即非字符a和b print(ret) #输出['4', '5', 'd', 'h', '3'] ret=re.findall('[\d]','45bdha3') #\d即匹配数字格式的字符 print(ret) #输出['4', '5', '3']
import re
ret=re.findall('c\l','abc\le') #元字符\的用法,可把一般字符和特殊字符相互转换,这里\l有特殊意义,所以字符串里检索不了 print(ret) #输出[] ret=re.findall('I\b','I am LIST') #\b表示匹配一个特殊字符,比如空格 ,&,#等 #\d表示匹配任何十进制数,相当于类 [0-9] #\D表示匹配任何非数字字符,相当于类[^0-9] #\s表示匹配任何空白字符,相当于类[ \t\n\r\f\v] #\S表示匹配任何非空白字符,相当于类[^\t\n\r\f\v] #\w表示匹配任何字母数字字符,相当于类[a-zA-Z0-9_] # \W表示匹配任何非字母数字字符,相当于类[^a-zA-Z0-9_] print(ret) #输出[] ret=re.findall(r'I\b','I am LIST') #\b有特殊意义,所以需再次转义\\b或r'\b' print(ret) #输出['I'] ret=re.findall('c\\l','abc\le') print(ret) #输出[] ret=re.findall('c\\\\l','abc\le') #python解释器转义和re转义有区别,所以需传入多个\来转义 print(ret) #输出['c\\l'] ret=re.findall(r'c\\l','abc\le') #直接在前面加r也可以再次转义 print(ret) #输出['c\\l']
m = re.findall(r'(ad)+', 'add') #元字符()的用法,将()里的内容作为整体来匹配 m = re.findall(r'(ad)+', 'adadad') #把ab看成一个整体 print(m) #由于优先匹配()组内的内容,所以优先输出['ad'] m1 = re.findall(r'(?:ad)+', 'adadad') #若要取消上述优先级,则需加上?: print(m1) #输出['ad','ad','ad'] ret=re.search('(ab)|\d','rabhdg8sd') print(ret.group()) #输出ab,re.search函数在字符串内查找匹配到第一个符合的子字符串则返回一个对象,可通过group()方法得到子符串,若没有匹配则返回None ret=re.search('(?P\d{2})/(?P ','23/com') #固定格式?P<分组名称>,id和name表示分组名称,不参与匹配 print(ret.group()) #输出23/com print(ret.group('id')) #输出23,group(分组名称)可以获取对应的值,分组的作用是可重用多次,提高效率\w{3})
re模块常用方法(上面已经讲了re.findall和re.search)
import re re.match('a','abc').group() #和re.search用法一样,但只能从字符串开始处进行匹配 ret=re.split('[ab]','abcd') #先按'a'分割,左边得到'',右边得到'bcd',再按b分割'bcd',左边得到'',右边得到'cd' print(ret) #输出['', '', 'cd'] ret=re.sub('\d','abc','alvin5yuan6',1) #参数1表示匹配规则或字符,参数2表示替换后的字符串,参数3表示被匹配的字符串,参数4表示匹配次数,不填则默认全部替换 print(ret) #输出alvinabcyuan6 ret=re.subn('\d','abc','alvin5yuan6') #能得到替换后的字符串和替换次数 print(ret) #输出('alvinabcyuanabc', 2) obj=re.compile('\d{3}') #先把规则给一个对象 ret=obj.search('abc123eeee') #对象调用模块方法 print(ret.group()) #输出123,优点是可重复调用,避免重复写规则,提高效率 ret=re.finditer('\d','ds3sy4784a') #将查找的内容生成迭代器 print(ret) #返回一个迭代器 print(next(ret).group()) #输出'3',可使用group迭代输出结果 print(next(ret).group()) #输出'4',对于数据比较大的常用这种迭代方法,不占内存
9、logging模块(※※※※※)
import logging logging.debug('debug message') #日志级别等级CRITICAL>ERROR>WARNING>INFO>DEBUG>NOTSET logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message') #输出WARNING:root:warning message # ERROR:root:error message # CRITICAL:root:critical message #日志默认级别为WARNING,打印本身及后面的,格式为日志级别:Logger名称:用户输出消息
import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='/tmp/test.log', filemode='w') #使用basicConfig设置格式,level设置日志级别;format指定显示格式;datefmt指定日期时间格式;
filename指定日志存储的文件名;filemode指定filename的文件打开方式,默认值为“a” logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message')#输出cat /tmp/test.log # Sun, 13 Oct 2019 16:29:53 test_logging.py[line:9] DEBUG debug message # Sun, 13 Oct 2019 16:29:53 test_logging.py[line:10] INFO info message # Sun, 13 Oct 2019 16:29:53 test_logging.py[line:11] WARNING warning message # Sun, 13 Oct 2019 16:29:53 test_logging.py[line:12] ERROR error message # Sun, 13 Oct 2019 16:29:53 test_logging.py[line:13] CRITICAL critical message
PS:上面的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:字符串形式的当前时间,默认格式 “2019-10-13 16:49:45,896”(逗号后面的是毫秒)
%(thread)d:线程ID,可能没有
%(threadName)s:线程名,可能没有
%(process)d:进程ID,可能没有
%(message)s:用户输出的消息
关于logger对象
import logging logger = logging.getLogger() #函数getLogger([name])返回一个logger对象,若无name则返回root logger fh = logging.FileHandler('test.log') #创建一个handler,用于写入日志文件 ch = logging.StreamHandler() #再创建一个handler,用于输出到控制台 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') #Formatter指定日志显示格式 fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) logger.addHandler(ch) #logger对象可以添加多个fh和ch对象 logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message') #输出2019-10-14 19:51:23,552 - root - WARNING - logger warning message # 2019-10-14 19:51:23,552 - root - ERROR - logger error message # 2019-10-14 19:51:23,552 - root - CRITICAL - logger critical message
PS:这里可以用logger.setLevel(logging.Debug)为logger设置日志级别,默认的日志级别为WARNIING,另外如果创建两个logger对象,如果参数name相同,返回的Logger实例就是同一个,后面个的日志级别则覆盖前面的日志级别,且后面的日志会把前面的再打印一遍
10、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加入数据,类似字典 config['bitbucket.org'] = {} config['bitbucket.org']['User'] = 'hg' config['topsecret.server.com'] = {} topsecret = config['topsecret.server.com'] topsecret['Host Port'] = '50022' topsecret['ForwardX11'] = 'no' config['DEFAULT']['ForwardX11'] = 'yes' with open('example.ini', 'w') as configfile: config.write(configfile)
操作:
import configparser config = configparser.ConfigParser() config.read('example.ini') #需要先进行read再进行查找操作 print(config.sections()) #输出除了第一个的key,为['bitbucket.org', 'topsecret.server.com'] print('bytebong.com' in config) #输出False print(config['bitbucket.org']['User']) #输出hg for key in config['topsecret.server.com']: print(key) #输出Port #ForwardX11 print(config.options('bitbucket.org')) #输出['user'],即key print(config.items('bitbucket.org')) #输出[('user', 'hg')],即整个items print(config.get('DEFAULT','compression')) #输出yes #---------------------------------------------------------------查找操作 config.add_section('yuan') #---------------------------------------------------------------增加操作 config.remove_section('topsecret.server.com') config.remove_option('bitbucket.org','user') #---------------------------------------------------------------删除操作 config.set('bitbucket.org','k1','11111') #---------------------------------------------------------------修改操作 config.write(open('i.cfg', "w")) #可以直接通过函数打开,不用关闭
11、hashlib模块(※※)
import hashlib m=hashlib.md5() #也可以用m=hashlib.sha256(),此模块主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法 m.update('hello'.encode('utf8')) #要进行哈希的的字符串“hello” print(m.hexdigest()) #输出5d41402abc4b2a76b9719d911017c592 m.update('alvin'.encode('utf8')) print(m.hexdigest()) #输出92a7e713c30abbb0319fa07da2a5c4af m2=hashlib.md5() #另外定义一个变量 m2.update('helloalvin'.encode('utf8')) #把前两个字符串连起来处理 print(m2.hexdigest()) #输出92a7e713c30abbb0319fa07da2a5c4af,即上面的m是先哈希hello,再加上alvin哈希
那么现在有一个很大的数据库,统计了很多常用的字符串,于是可能会被反解,称为撞库。为了避免这种情况可以用以下这种方法:
import hashlib m = hashlib.sha256('898oaFs09f'.encode('utf8')) #在处理之前加一段哈希的随机字符串 m.update('alvin'.encode('utf8')) print(m.hexdigest())#输出04d0625659c27032274faf030cd842676be3b8912bb255f9d3445d86c1e5de80
当然python还有一个hmac模块,它内部对我们创建key和内容,然后再进行处理后加密:
import hmac h = hmac.new('alvin'.encode('utf8')) h.update('hello'.encode('utf8')) print (h.hexdigest()) #输出320df9832eab4c038b6c1d7ed73a5940