week5
1 定义
模块: 用来从逻辑上组织python代码,本质是.py结尾的python文件。
包:用来从逻辑上组织模块的,本质是一个目录(必须存在一个_init_.py文件)。
2 导入方法
import module_name
import module1_name,module2_name
from module_name import * #导入module中所有内容,不建议使用,不能通过module_name.方式调用模块中的函数,而是直接通过函数名调用
from module_name import def1_name,def2_name
from module_name import def_name as 别名
3 import本质
import module_name ----> module_name = all code #将module代码解释后赋值给module_name
from module_name import def_name ---> 将 def_name 直接复制到当前文件中执行
导入模块的本质就是把python文件解释一遍。
导入包的本质就是执行该包下的_init_.py文件。
4 导入优化
import module_name ---> module_name.py ---> module_name.py的路径 ---> sys.path
import os import sys print(__file__) # 打印相对路径 print(os.path.abspath(__file__)) # 打印绝对路径 print(os.path.dirname(os.path.abspath(__file__))) # 父目录路径 print(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # 父父目录路径 PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(PATH) # 加入环境变量 sys.path是个list,可以使用sys.path.insert插入 from core import main main.atm()
在_init_文件导入模块:from . import module_name #在当前目录下导入module
在python文件中导入包:import passage_name,可以在文件中passage_name.module_name.def_name调用module中的方法
5 模块分类
- 标准库(内置模块);
- 开源模块(第三方模块);
- 自定义模块。
5.1 时间模块(time&datatime)
5.1.1 时间表示形式
UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。
表示时间方式:1)时间戳 2)格式化的时间字符串 3)元组(struct_time)共九个元素。
import time # <1> 时间戳 print(time.time()) # 时间戳:1521424491.5176704 # <2> 时间字符串 print(time.strftime("%Y-%m-%d %X")) #格式化的时间字符串:'2018-03-19 09:54:51' # <3> 时间元组 print(time.localtime()) #本地时区的struct_time:'time.struct_time(tm_year=2018, tm_mon=3, tm_mday=19, tm_hour=9, tm_min=54, tm_sec=51, tm_wday=0, tm_yday=78, tm_isdst=0)' print(time.gmtime()) #UTC时区的struct_time:isdst为时区
5.1.2 时间的转换
#时间戳<- - ->结构化时间: localtime/gmtime/mktime print(time.localtime(3600*24)) print(time.gmtime(3600*24)) print(time.mktime(time.localtime())) #字符串时间<- - ->结构化时间: strftime/strptime print(time.strftime("%Y-%m-%d %X", time.localtime())) print(time.strptime("2017-03-16","%Y-%m-%d"))
print(time.asctime(time.localtime())) print(time.ctime(1521425493.0))
5.1.3 其他方法
#延迟时间
time.sleep(seconds)
#时间加减
import datetime
print(datetime.datetime.now()) #返回当前时间 2018-03-19 10:17:39.694514
print(datetime.date.fromtimestamp(time.time()) ) # 时间戳直接转成日期格式 2018-03-19
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)) #时间替换
5.2 ramdon模块
import random print(random.random()) # (0,1)float 大于0且小于1之间的小数 print(random.randint(1, 3)) # [1,3] 大于等于1且小于等于3之间的整数 print(random.randrange(1, 3)) # [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的小数,如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(4))
5.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下为" ",Linux下为" " 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的大小 '''
5.4 sys模块
''' sys.argv 命令行参数List,第一个元素是程序本身路径,可传参 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sys.maxint 最大的Int值 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称 '''
5.5 shutil模块
import shutil f1= open('file1','r',encoding='utf-8') f2= open('file2','w',encoding='utf-8') shutil.copyfileobj(f1,f2) #将文件内容拷贝到另一个文件中
import shutil shutil.copyfile('file2','file3') #拷贝文件,不需要打开文件,目标文件无需存在
import shutil shutil.copymode('file1','file2') #仅拷贝权限,内容、组、用户均不变,目标文件必须存在
import shutil shutil.copystat('file1','file3') #仅拷贝状态的信息,包括:mode bits, atime, mtime, flags,目标文件必须存在
import shutil shutil.copy('file1','file2')#拷贝文件和权限
import shutil shutil.copy2('file1','file2')#拷贝文件和状态信息
import shutil shutil.copytree('a','copy_a') #递归的去拷贝文件夹
import shutil shutil.rmtree('copy_a') #递归的去删除文件
import shutil shutil.move('file3','a')#递归的去移动文件,它类似mv命令
压缩文件:
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如 data_bak---->保存至当前路径
如:/tmp/data_bak--->保存至/tmp/
- format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
import shutil shutil.make_archive('archive_test','zip',r'C:UserszhouxyPycharmProjectsuntitledday4') #讲某路径下所有文件压缩到当前路径
import zipfile z = zipfile.ZipFile('file.zip','w') #在当前路径下压缩指定文件 z.write('file1') print('-----') z.write('file2') z.close()
解压文件:
import zipfile z = zipfile.ZipFile('archive_test.zip', 'r') z.extractall() z.close()
5.6 json&pickle模块
5.6.1 序列化原因
1.持久保存状态
2.跨平台数据交互
5.6.2 序列化方式
5.7 shelve模块
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式。
import shelve d = shelve.open('shelve_test') #打开一个文件 name = ["zhouxy", "female", 18] d["test"] = name # 持久化列表 d['info']={'name':'zhouxy','age':18} #持久化dict print(d.get('test')) print(d.get('info')) d.close()
5.8 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>
import xml.etree.cElementTree as ET tree = ET.parse('xml_test.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,i.attrib) #遍历year节点 for note in root.iter('year'): print(note.tag,note.text)
import xml.etree.cElementTree as ET tree = ET.parse('xml_test.xml') root = tree.getroot() #修改 for node in root.iter('year'): new_year = int(node.text)+1 node.text = str(new_year) node.set('updated','zhouxy') #增加属性 tree.write('xml_test.xml') #删除 for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('xml_test.xml')
创建xml文档
import xml.etree.ElementTree as ET name_xml = ET.Element("namelist") #创建根节点并赋值给一个对象 name = ET.SubElement(name_xml, "name", attrib={"enrolled": "yes"}) #创建一级子节点 name.text = 'zhouxy' age = ET.SubElement(name, "age", attrib={"checked": "no"}) #创建二级子节点 age.text = '18' sex = ET.SubElement(name, "sex") #创建二级子节点 sex.text = 'F' name2 = ET.SubElement(name_xml, "name", attrib={"enrolled": "no"}) age = ET.SubElement(name2, "age") et = ET.ElementTree(name_xml) # 生成文档对象 et.write("name.xml", encoding="utf-8", xml_declaration=True) ET.dump(name_xml) # 打印生成的格式
5.9 ConfigParser模块
用于生成和修改常见配置文档。文档格式如下:

[DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port = 50022 ForwardX11 = no
import configparser # python2.X 为 ConfigParser config = configparser.ConfigParser() # 创建一个config对象 config["DEFAULT"] = {'ServerAliveInterval': '45', 'Compression': 'yes', 'CompressionLevel': '9'} config['DEFAULT']['ForwardX11'] = 'yes' config['bitbucket.org'] = {} config['bitbucket.org']['User'] = 'hg' config['topsecret.server.com'] = {} topsecret = config['topsecret.server.com'] topsecret['Host Port'] = '50022' topsecret['ForwardX11'] = 'no' with open('example.conf', 'w') as configfile: config.write(configfile)
# 读取 import configparser config=configparser.ConfigParser() config.read('db.conf') print(config.defaults()) # 查看default所有内容 print(config.sections()) #查看所有的标题 print(config.options('bitbucket.org')) #查看标题bitbucket.org和default下所有key=value的key,与default相同的key不重复显示 print(config.items('bitbucket.org')) #查看标题bitbucket.org下和default所有key=value的(key,value)格式 print(config.get('bitbucket.org','User')) #查看标题bitbucket.org下User的值=>字符串格式 print(config.getint('DEFAULT','ServerAliveInterval'))#查看标题default下ServerAliveInterval的值=>整数格式 print(config.getboolean('DEFAULT','ForwardX11')) #查看标题default下ForwardX11的值=>布尔值格式 print(config.getfloat('topsecret.server.com','Port')) #查看标题topsecret.server.com下Port的值=>浮点型格式
import configparser config=configparser.ConfigParser() config.read('example.conf',encoding='utf-8') config.remove_section('bitbucket.org') #删除整个标题bitbucket.org config.remove_option('topsecret.server.com','ForwardX11') #删除标题topsecret.server.com下的某个ForwardX11 print(config.has_section('bitbucket.org')) #判断是否存在某个标题 print(config.has_option('topsecret.server.com','ForwardX11')) #判断标题topsecret.server.com和default下是否存在ForwardX11 config.add_section('zhouxy') #添加一个标题 config.set('zhouxy','name','zhouxy') #在标题zhouxy下添加name=zhouxy,age=18的配置 #config.set('egon','age',18) #报错,必须是字符串 config.write(open('example.conf','w')) #最后将修改的内容写入文件,完成最终的修改
5.10 hashlib模块
hash:一种加密算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法。
三个特点:
- 内容相同则hash运算结果相同,内容稍微改变则hash值则变;
- 不可逆推;
- 相同算法:无论校验多长的数据,得到的哈希值长度固定。
import hashlib m = hashlib.md5() m.update('hello'.encode('utf-8')) #5d41402abc4b2a76b9719d911017c592 print(m.hexdigest()) m.update('it’s me'.encode('utf-8')) #无论update多少次,校验的内容累加到一起是一样的内容 e36c615cdab6d98c413121f3b90de97a
print(m.hexdigest())
m2 = hashlib.md5()
m2.update('helloit’s me'.encode('utf-8'))
print(m2.hexdigest()) #16进制格式hash e36c615cdab6d98c413121f3b90de97a
print(m2.digest()) #2进制格式hash
python 还有一个 hmac 模块。
散列消息鉴别码,简称HMAC,是一种基于消息鉴别码MAC(Message Authentication Code)的鉴别机制。使用HMAC时,消息通讯的双方,通过验证消息中加入的鉴别密钥K来鉴别消息的真伪。一般用于网络通信中消息加密,前提是双方先要约定好key,就像接头暗号一样,然后消息发送把用key把消息加密,接收方用key+消息明文再加密,拿加密后的值 跟发送者的相对比是否相等,这样就能验证消息的真实性,及发送者的合法性了。
import hmac h = hmac.new('阿里巴巴'.encode('utf-8'),'芝麻开门'.encode('utf-8')) print(h.hexdigest()) h2 = hmac.new('阿里巴巴'.encode('utf-8')) h2.update('芝麻开门'.encode('utf-8')) print(h2.hexdigest())
5.11 re模块
re模块用于对python的正则表达式的操作。
元字符:. ^ $
import re #默认匹配除 之外的任意一个字符 ret1=re.findall('李.','李一 a 李二 b c 李三') #['李一', '李二', '李三'] #匹配字符开头A ret2=re.findall('^李.','李一 a 李二 b c 李三') #['李一'] #匹配字符结尾 ret3=re.findall('李.$','李一 a 李二 b c 李三') #['李三']
* + ? { }
import re #匹配*号前的字符0次或多次 ret1=re.findall('李.*','李一 a 李二 b c 李三') #['李一', '李二', '李三'] #匹配前一个字符1次或多次 ret2=re.findall('李.+','李一 a 李二 b c 李三') #['李一', '李二', '李三'] #匹配前一个字符n到m次 ret3=re.findall('(李.{1,2}) ','李一 a 李二 b c 李三') #设定优先级的原因 #['李一', '李二'] #匹配一个数字包括整型和浮点型 ret4=re.findall('d+.?d*','12.45,34,0.05,109') #['12.45', '34', '0.05', '109']
注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配。
ret=re.findall('13d+?','1312312312') print(ret) #['131']
转义符
d 匹配任何十进制数; 它相当于类 [0-9]。 D 匹配任何非数字字符; 它相当于类 [^0-9]。 s 匹配任何空白字符; 它相当于类 [ fv]。 S 匹配任何非空白字符; 它相当于类 [^ fv]。 w 匹配任何字母数字字符; 它相当于类 [a-zA-Z0-9_]。 W 匹配任何非字母数字字符; 它相当于类 [^a-zA-Z0-9_] 匹配一个特殊字符边界,比如空格 ,&,#等,
分组 ()
m = re.findall(r'(ad)+', 'add') print(m) #['ad'] ret = re.search('(?P<id>d{2})/(?P<name>w{3})', '23/com') print(ret.group()) # 23/com print(ret.group('id')) # 23
元字符之|
#匹配|左或|右的字符 ret=re.search('(ab)|d','rabhdg8ab') print(ret.group())#ab
字符集[]
ret1 = re.findall('a[bc]d', 'acd') print(ret1) # ['acd'] ret2 = re.findall('[a-z]', 'acd') print(ret2) # ['a', 'c', 'd'] ret3 = re.findall('[.*+]', 'a.cd+') print(ret3) # ['.', '+'] # 在字符集里有功能的符号: - ^ ret4 = re.findall('[1-9]', '45dha3') print(ret4) # ['4', '5', '3'] ret5 = re.findall('[^ab]', '45bdha3') print(ret5) # ['4', '5', 'd', 'h', '3'] ret6 = re.findall('[d]', '45bdha3') print(ret6) # ['4', '5', '3']
常用方法
match() # 同search,不过仅在字符串开始处进行匹配
search() # 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
findall() # 返回所有满足匹配条件的结果,放在列表里
split('[ab]', 'abcd') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
sub('a','A','appleapc',2)) # AppleApc
ret = re.search('(?P<num>[0-9]{2})(?P<name>[a-z]+)','abc123zxy321').groupdict() #{'num': '23', 'name': 'zxy'}
几个匹配模式
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同) M(MULTILINE): 多行模式,改变'^'和'$'的行为 S(DOTALL): 点任意匹配模式,改变'.'的行为